home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / viewers / polyview / polyvw31.lha / Polyview3.1 / new / pvdraw.c < prev    next >
C/C++ Source or Header  |  1993-06-23  |  81KB  |  2,888 lines

  1. /*****************************************************************************
  2.  * NCSA Polyview 3.0                                                         *
  3.  *                                                                           *
  4.  * Version 3 changes and additions by Marc Andreessen.                       *
  5.  * Version 2 by Brian Calvert.                                               *
  6.  *                                                                           *
  7.  * Software Development Group                                                *
  8.  * National Center for Supercomputing Applications                           *
  9.  * University of Illinois at Urbana-Champaign                                *
  10.  *                                                                           *
  11.  * This is BETA release software.  As such it may contain software bugs and  *
  12.  * exhibit inconsistencies.                                                  *
  13.  *                                                                           *
  14.  * Please send bug reports to polyview@ncsa.uiuc.edu.                        *
  15.  *                                                                           *
  16.  * Copyright (c) 1992 The Board of Trustees of the University of Illinois.   *
  17.  *                                                                           *
  18.  * Permission to use, copy, and modify this software and its                 *
  19.  * documentation for educational, research, and non-profit purposes is       *
  20.  * hereby granted, provided that the above copyright notice, the original    *
  21.  * authors names, and this permission notice appear in all such copies.      *
  22.  * Any distribution of this software requires the explicit and written       *
  23.  * authorization of the authors.                                             *
  24.  *                                                                           *
  25.  * The University of Illinois makes no representations about the             *
  26.  * suitability of this software for any purpose.  It is provided "as is"     *
  27.  * without warranty of any kind.                                             *
  28.  *****************************************************************************/
  29.  
  30. /* $Header: /usr3/people/gbourhis/pv3/new/RCS/pvdraw.c,v 1.3 92/09/30 18:46:20 marca Exp $ */
  31.  
  32. #ifdef RCSLOG
  33. $Log:    pvdraw.c,v $
  34.  * Revision 1.3  92/09/30  18:46:20  marca
  35.  * Better checking for single-color palette.
  36.  * 
  37.  * Revision 1.2  1992/09/19  03:43:08  marca
  38.  * Made picked-vertex jack bigger.
  39.  *
  40.  * Revision 1.1  1992/09/18  10:55:26  marca
  41.  * Initial revision
  42.  *
  43. #endif
  44.  
  45. #include "pv.h"
  46.  
  47. #ifdef __sgi
  48. #include <gl/sphere.h>
  49. #endif /* __sgi */
  50.  
  51. #ifdef _IBMR2
  52. #include "/usr/lpp/GL/utilities/inc/sphere.h"
  53. #endif /* _IBMR2 */
  54.  
  55. static float nn[3];
  56.  
  57. #define PI 3.1415926
  58.  
  59.  
  60. /* This function loads local array nn with the normal, after
  61.    computing it and normalizing. */
  62. static void find_normal (float p1[3], float p2[3], float p3[3])
  63. {
  64.   static float t1[3], t2[3], temp;
  65.   
  66.   t1[0] = p2[0] - p1[0]; 
  67.   t1[1] = p2[1] - p1[1]; 
  68.   t1[2] = p2[2] - p1[2]; 
  69.   t2[0] = p2[0] - p3[0];
  70.   t2[1] = p2[1] - p3[1];
  71.   t2[2] = p2[2] - p3[2];
  72.  
  73.   nn[0]= t1[1] * t2[2] - t2[1] * t1[2];
  74.   nn[1]= t1[2] * t2[0] - t2[2] * t1[0];
  75.   nn[2]= t1[0] * t2[1] - t2[0] * t1[1];
  76.  
  77.   temp = 1.0 / sqrt((nn[0] * nn[0]) + (nn[1] * nn[1]) + (nn[2] * nn[2]));
  78.   nn[0] *= temp;
  79.   nn[1] *= temp;
  80.   nn[2] *= temp;
  81.  
  82.   return;
  83. }
  84.  
  85.  
  86.  
  87. /* Grab zbuffer values for the first time in the program and
  88.    store them in the global state.  Also figure out what values
  89.    we should use for drawing polygons in outlined polygon mode
  90.    so the outlines actually !%#@$%#$@!!%#$@ show up. */
  91. #define ZBUF_COMPRESS /* 0x2ff */ 0x10f
  92.  
  93. void init_zbuffer (void)
  94. {
  95.   /* Set up Zbuffer values. */
  96.   gstate->zmin = getgdesc (GD_ZMIN);
  97.   gstate->zmax = getgdesc (GD_ZMAX);
  98.  
  99.   /* Figure out compressed values for Zbuffer. */
  100.   if (gstate->zmin > gstate->zmax)
  101.     {
  102.       /* reduce zmin, increase zmax */
  103.       gstate->zmin_comp = gstate->zmin - ZBUF_COMPRESS;
  104.       gstate->zmax_comp = gstate->zmax + ZBUF_COMPRESS;
  105.     }
  106.   else
  107.     {
  108.       /* increase zmin, reduce zmax */
  109.       gstate->zmin_comp = gstate->zmin + ZBUF_COMPRESS;
  110.       gstate->zmax_comp = gstate->zmax - ZBUF_COMPRESS;
  111.     }
  112.  
  113.   return;
  114. }
  115.  
  116.  
  117. /* ------------------------------------------------------------------------ */
  118. /* -------------------------- SQUEEZED Z-BUFFER --------------------------- */
  119. /* ------------------------------------------------------------------------ */
  120.  
  121. static long zmin_comp, zmax_comp;
  122.  
  123. /* This routine loads local static variables zmin_comp and zmax_comp
  124.    with appropriate values for a given window; thereafter, a call to
  125.    set_squeezed_zbuffer will to lsetdepth with those values. */
  126. void grok_squeezed_zbuffer (state_t *state, window_t *win)
  127. {
  128.   float zmult, zexp;
  129.   long zfactor;
  130.  
  131.   zmult = WIN_SFROM(win)[RHO] / WIN_MAXWIDTH(win);
  132.  
  133.   zexp = exp(zmult);
  134.   zfactor = (long)((float)ZBUF_COMPRESS * zexp);
  135.   if (zmult > 1.02)
  136.     zfactor *= zexp * 0.6;
  137.   if (zmult > 1.2)
  138.     zfactor *= zexp;
  139.   if (zmult < 0.8)
  140.     zfactor /= zmult;
  141.  
  142.   /* Figure out compressed values for Zbuffer. */
  143.   if (state->zmin > state->zmax)
  144.     {
  145.       /* reduce zmin, increase zmax */
  146.       zmin_comp = state->zmin - zfactor;
  147.       zmax_comp = state->zmax + zfactor;
  148.     }
  149.   else
  150.     {
  151.       /* increase zmin, reduce zmax */
  152.       zmin_comp = state->zmin + zfactor;
  153.       zmax_comp = state->zmax - zfactor;
  154.     }
  155.  
  156.   return;
  157. }
  158.  
  159.  
  160. /* This routine does an lsetdepth to accommodate a squeezed zbuffer,
  161.    with the particular squeeze values having been determined by
  162.    a call to grok_squeezed_zbuffer above. */
  163. void set_squeezed_zbuffer (void)
  164. {
  165. #if 0
  166.   lsetdepth (gstate->zmax_comp, gstate->zmin_comp);
  167. #else
  168.   lsetdepth (zmax_comp, zmin_comp);
  169. #endif
  170.  
  171.   return;
  172. }
  173.  
  174.  
  175. int redraw_windows(state_t *state)
  176. {
  177.   window_t *win;
  178.   polyview_t *pv;
  179.   int status;
  180.     
  181.   /* Initialize status flag.  If any errors occurred during redraws, */
  182.   /* will tell us. */
  183.   status = ST_OKAY;
  184.  
  185.   /* Redraw every window that has its please_redraw flag set to TRUE. */
  186.   for (win = state->windows; win != NULL; win = win->next) 
  187.     {
  188.       if ((win->please_redraw == TRUE) &&
  189.           (win->redraw_fn != NULL))
  190.           {
  191.             if (win->type == POLYVIEW)
  192.               {
  193.                 /* Focus GL on this window. */
  194.                 pv = (polyview_t *)WIN_IMAGE(win);
  195.                 XmxWinset (pv->drawing_volume);
  196.  
  197.                 /* Figure out the center of the window. */
  198.                 win->cx = pv->dv_width / 2;
  199.                 win->cy = pv->dv_height / 2;
  200.                 
  201.                 /* Reset the redraw request flag and call the */
  202.                 /* redraw function, checking its return value. */
  203.                 win->please_redraw = FALSE;
  204.                 win->animated = FALSE;
  205.                 if ((*win->redraw_fn)(state, win) != ST_OKAY)
  206.                   status = ST_ERROR;
  207.                 
  208.                 /* If the window is continuously writing out raster */
  209.                 /* image, write one out now. */
  210.                 if (IsRasterContinuous(win))
  211.                   WriteRaster(state, win, WIN_RASTERNAME(win));
  212.                 if (IsRasterBlastContinuous(win))
  213.                   WriteRasterOverDTM(state, win);
  214.           
  215.                 /* Inform other windows that this window has redrawn. */
  216.                 broadcast_msg
  217.                   (state, win, MSG_REDRAW, state->active_windows);
  218.               }
  219.             else if (win->type == PALETTE)
  220.               {
  221.                 /* We can't XmxWinset here because the wid is
  222.                    stored local to pvpal.c. */
  223.                 win->please_redraw = FALSE;
  224.                 if ((*win->redraw_fn)(state, win) != ST_OKAY)
  225.                   status = ST_ERROR;
  226.  
  227.                 broadcast_msg
  228.                   (state, win, MSG_REDRAW, state->active_windows);
  229.               }
  230.             else
  231.               {
  232.                 /* this is a window that doesn't need to be redrawn */
  233.                 win->please_redraw = FALSE;
  234.               }
  235.           }
  236.     }
  237.  
  238.   return status;
  239. }
  240.  
  241.  
  242. int set_redraw(state_t *state, window_t *win)
  243. {
  244.   /* A NULL window pointer is an error. */
  245.   assert (win != NULL);
  246.   
  247.   /* Reset the window's redraw request flag.  The next time the process */
  248.   /* events routine exists it will redraw the windows. */
  249.   win->please_redraw = TRUE;
  250.   return ST_OKAY;
  251. }
  252.  
  253.  
  254. /* SetOpacity sets the system to draw polygons at the specified alpha */
  255. /* level, where alpha is a floating point number in the range [0, 1]. */
  256. /* On some systems this is implemented using patterns, on others using */
  257. /* alpha buffering; currently we use only patterns. */
  258. void SetOpacity(float alpha)
  259. {
  260.   /* Use a pattern to approximate the transparency level.  An */
  261.   /* alpha level of 1.0 is a special case. */
  262.   if ((alpha >= 0.0) && (alpha <= 1.00))
  263.     {
  264.       if (FEQ (alpha, 1.0))
  265.         setpattern(0);
  266.       else
  267.         setpattern(1 + (short)(alpha * 17));
  268.     }
  269.   else
  270.     setpattern (0);
  271.  
  272.   return;
  273. }
  274.  
  275.  
  276. /* Draw the small axes for a pick selection. */
  277. void DrawJack(float (*p)[DIMS], float off)
  278. {
  279.   float x = (*p)[X];
  280.   float y = (*p)[Y];
  281.   float z = (*p)[Z];
  282.  
  283.   linewidth (2);
  284.   
  285.   bgnline();
  286.   v3f(p3f(x-off, y, z));
  287.   v3f(p3f(x+off, y, z));
  288.   endline();
  289.   
  290.   bgnline();
  291.   v3f(p3f(x, y-off, z));
  292.   v3f(p3f(x, y+off, z));
  293.   endline();
  294.   
  295.   bgnline();
  296.   v3f(p3f(x, y, z-off));
  297.   v3f(p3f(x, y, z+off));
  298.   endline();
  299.  
  300.   linewidth (1);
  301.  
  302.   return;
  303. }
  304.  
  305.  
  306. int draw_grid (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
  307.                int plane)
  308. {
  309.   int i, j;
  310.   float    xinc, yinc, zinc;
  311.   float    xmin, ymin, zmin;
  312.   float    xmax, ymax, zmax;
  313.   float vv[3];
  314.   float    mwoff, xoff, yoff, zoff;
  315.     
  316.   if (plane != 0) 
  317.     {
  318.       /* Get the minimal x, y, z values and initialize the */
  319.       /* incremental values to zero. */
  320.       mwoff = WIN_MAXWIDTH(win) / 200.0;
  321.       
  322.       xmin = WIN_STATS(win,PX).min - mwoff;
  323.       ymin = WIN_STATS(win,PY).min - mwoff;
  324.       zmin = WIN_STATS(win,PZ).min - mwoff;
  325.       
  326.       xmax = WIN_STATS(win,PX).max + mwoff;
  327.       ymax = WIN_STATS(win,PY).max + mwoff;
  328.       zmax = WIN_STATS(win,PZ).max + mwoff;
  329.       
  330.       xinc = yinc = zinc = 0.0;
  331.     
  332.       /* Set the incremental values if the dimension is mentioned  */
  333.       /* in the plane. */
  334.       if (plane & (GRIDXY | GRIDXZ))
  335.         {
  336.           xinc = (xmax - xmin) * 0.1;
  337.           xoff = (xmax - xmin) * 0.01;
  338.         }
  339.       if (plane & (GRIDXY | GRIDYZ))
  340.         {
  341.           yinc = (ymax - ymin) * 0.1;
  342.           yoff = (ymax - ymin) * 0.01;
  343.         }
  344.       if (plane & (GRIDXZ | GRIDYZ))
  345.         {
  346.           zinc = (zmax - zmin) * 0.1;
  347.           zoff = (zmax - zmin) * 0.01;
  348.         }
  349.       
  350.       SetOpacity (0.3);
  351.       cpack(FOREGROUND);
  352.  
  353.       if (plane & GRIDXY)
  354.         {
  355.           for (i = 0; i < 10; i++) /* X */
  356.             for (j = 0; j < 10; j++) /* Y */
  357.               {
  358.                 bgnpolygon();
  359.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  360.                 vv[Y] = ymin + ((float)j * yinc) + yoff;
  361.                 vv[Z] = zmin;
  362.                 v3f (vv);
  363.                 vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
  364.                 v3f (vv);
  365.                 vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
  366.                 v3f (vv);
  367.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  368.                 v3f (vv);
  369.                 endpolygon ();
  370.               }
  371.         }
  372.       
  373.       if (plane & GRIDXZ)
  374.         {
  375.           for (i = 0; i < 10; i++) /* X */
  376.             for (j = 0; j < 10; j++) /* Z */
  377.               {
  378.                 bgnpolygon();
  379.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  380.                 vv[Y] = ymin;
  381.                 vv[Z] = zmin + ((float)j * zinc) + zoff;
  382.                 v3f (vv);
  383.                 vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
  384.                 v3f (vv);
  385.                 vv[Z] = zmin + ((float)(j + 1) * zinc) - zoff;
  386.                 v3f (vv);
  387.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  388.                 v3f (vv);
  389.                 endpolygon ();
  390.               }
  391.         }
  392.       
  393.       if (plane & GRIDYZ)
  394.         {
  395.           for (i = 0; i < 10; i++) /* Z */
  396.             for (j = 0; j < 10; j++) /* Y */
  397.               {
  398.                 bgnpolygon();
  399.                 vv[X] = xmin;
  400.                 vv[Y] = ymin + ((float)j * yinc) + yoff;
  401.                 vv[Z] = zmin + ((float)i * zinc) + zoff;
  402.                 v3f (vv);
  403.                 vv[Z] = zmin + ((float)(i + 1) * zinc) - zoff;
  404.                 v3f (vv);
  405.                 vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
  406.                 v3f (vv);
  407.                 vv[Z] = zmin + ((float)i * zinc) + zoff;
  408.                 v3f (vv);
  409.                 endpolygon ();
  410.               }
  411.         }
  412.       
  413.       SetOpacity (1.0);
  414.  
  415.       if (plane & GRIDXY)
  416.         {
  417.           for (i = 0; i < 10; i++) /* X */
  418.             for (j = 0; j < 10; j++) /* Y */
  419.               {
  420.                 bgnclosedline();
  421.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  422.                 vv[Y] = ymin + ((float)j * yinc) + yoff;
  423.                 vv[Z] = zmin;
  424.                 v3f (vv);
  425.                 vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
  426.                 v3f (vv);
  427.                 vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
  428.                 v3f (vv);
  429.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  430.                 v3f (vv);
  431.                 endclosedline ();
  432.               }
  433.         }
  434.       
  435.       if (plane & GRIDXZ)
  436.         {
  437.           for (i = 0; i < 10; i++) /* X */
  438.             for (j = 0; j < 10; j++) /* Z */
  439.               {
  440.                 bgnclosedline();
  441.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  442.                 vv[Y] = ymin;
  443.                 vv[Z] = zmin + ((float)j * zinc) + zoff;
  444.                 v3f (vv);
  445.                 vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
  446.                 v3f (vv);
  447.                 vv[Z] = zmin + ((float)(j + 1) * zinc) - zoff;
  448.                 v3f (vv);
  449.                 vv[X] = xmin + ((float)i * xinc) + xoff;
  450.                 v3f (vv);
  451.                 endclosedline ();
  452.               }
  453.         }
  454.       
  455.       if (plane & GRIDYZ)
  456.         {
  457.           for (i = 0; i < 10; i++) /* Z */
  458.             for (j = 0; j < 10; j++) /* Y */
  459.               {
  460.                 bgnclosedline();
  461.                 vv[X] = xmin;
  462.                 vv[Y] = ymin + ((float)j * yinc) + yoff;
  463.                 vv[Z] = zmin + ((float)i * zinc) + zoff;
  464.                 v3f (vv);
  465.                 vv[Z] = zmin + ((float)(i + 1) * zinc) - zoff;
  466.                 v3f (vv);
  467.                 vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
  468.                 v3f (vv);
  469.                 vv[Z] = zmin + ((float)i * zinc) + zoff;
  470.                 v3f (vv);
  471.                 endclosedline ();
  472.               }
  473.         }
  474.     }
  475.   
  476.   return ST_OKAY;
  477. }
  478.  
  479.  
  480.  
  481. int draw_scatter (state_t *state, window_t *win, object_t *obj, int (*fn)(),
  482.                   objinfo_t *info, int plane)
  483. {
  484.   float    xmin, ymin, zmin;
  485.   float    mwoff;
  486.   Vdata_t *vcolor;
  487.   int light;
  488.   
  489.   if (plane != 0) 
  490.     {
  491.       /* Get the minimal x, y, z values and initialize the */
  492.       /* incremental values to zero. */
  493.       mwoff = WIN_MAXWIDTH(win) / 200.0;
  494.       
  495.       xmin = WIN_STATS(win,PX).min - mwoff;
  496.       ymin = WIN_STATS(win,PY).min - mwoff;
  497.       zmin = WIN_STATS(win,PZ).min - mwoff;
  498.       
  499.       /* Check to see which plane the data are to be drawn in. */
  500.       /* Scale them appropriately. */
  501.       pushmatrix();
  502.       if (plane == SCATXY) 
  503.         {
  504.           translate(0.0, 0.0, zmin);
  505.           scale(1.0, 1.0, 0.0);
  506.         }
  507.       if (plane == SCATXZ) 
  508.         {
  509.           translate(0.0, ymin, 0.0);
  510.           scale(1.0, 0.0, 1.0);
  511.         }
  512.       if (plane == SCATYZ) 
  513.         {
  514.           translate(xmin, 0.0, 0.0);
  515.           scale(0.0, 1.0, 1.0);
  516.         }
  517.       
  518.       /* Draw the data in black and white. */
  519.       /* This is very very very cheesy. */
  520.       vcolor = OBJ_VDATA(obj,VCOLOR);
  521.       OBJ_VDATA(obj,VCOLOR) = NULL;
  522.       
  523.       /* Turn lighting off. */
  524.       light = WIN_LIGHT(win);
  525.       WIN_LIGHT(win) = 0;
  526.       
  527.       SetOpacity (0.6);
  528.  
  529.       /* If we're drawing outlined faces or hidden edges, shadows should
  530.          only be faces; otherwise we draw shadows same as objects. */
  531.       if (fn == draw_outlined_faces || fn == draw_hidden_edges)
  532.         draw_faces (state, win, obj, info);
  533.       else
  534.         (*fn)(state, win, obj, info);
  535.       
  536.       SetOpacity (1.0);
  537.       
  538.       OBJ_VDATA(obj,VCOLOR) = vcolor;
  539.       WIN_LIGHT(win) = light;
  540.       
  541.       popmatrix();
  542.     }
  543.   
  544.   return ST_OKAY;
  545. }
  546.  
  547.  
  548. int draw_axis (state_t *state, window_t *win, float start[DIMS], 
  549.                float end[DIMS], int axis)
  550. {
  551.   int i;
  552.   float    range, incr, tic_start[DIMS], tic_end[DIMS], mwoff;
  553.   double mag;
  554.   char value[MAXNAMELEN];
  555.   
  556.   /* Decide which axis is being drawn here. */
  557.   mwoff = WIN_MAXWIDTH(win) / 200.0;
  558.   for (i = X; i < DIMS; i++) 
  559.     {
  560.       /* Copy the value of the axis to the tic arrays. */
  561.       tic_start[i] = start[i];
  562.       tic_end[i] = start[i];
  563.       
  564.       if (i != axis) 
  565.         {
  566.           /* The non-axis values should be adjusted by a */
  567.           /* fraction of the max width to produce tics. */
  568.           tic_start[i] -= mwoff;
  569.           tic_end[i] += mwoff;
  570.           
  571.           /* Only modify the first dimension encountered. */
  572.           mwoff = 0.0;
  573.         }
  574.     }
  575.   
  576.   /* Get the range of values to be have tic marks drawn over. */
  577.   range = end[axis] - start[axis];
  578.   mag = floor(log10(range)+0.5);
  579.   incr = 2.0 * (float) pow((double) 10.0, mag - 1.0);
  580.   
  581.   /* Draw the tic marks. */
  582.   cpack(FOREGROUND);
  583.   do 
  584.     {
  585.       tic_start[axis] += incr;
  586.       tic_end[axis] += incr;
  587.       bgnline();
  588.       v3f(tic_start);
  589.       v3f(tic_end);
  590.       endline();
  591.     } 
  592.   while (tic_start[axis] < end[axis]);
  593.   
  594.   /* Calculate the final position. */
  595.   for (i = X; i < DIMS; i++)
  596.     end[i] = (tic_start[i]+tic_end[i])/2.0;
  597.   
  598.   /* Draw the axis. */
  599.   linewidth(2);
  600.   bgnline();
  601.   v3f(start);
  602.   v3f(end);
  603.   endline();
  604.   linewidth(1);
  605.   
  606.   /* Label the maximum value. */
  607.   cmov(end[X], end[Y], end[Z]);
  608.   sprintf(value, "%4g", end[axis]);
  609.   charstr(value);
  610.   
  611.   return ST_OKAY;
  612. }
  613.  
  614.  
  615. int draw_axes (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
  616.                int style)
  617. {
  618.   if (style & AXESLARGE) 
  619.     {
  620.       float corner[4][DIMS];
  621.       stats_t *stats;
  622.       
  623.       stats = win->stats[0];
  624.       /* Assign coordinates to the corners of the axes. */
  625.       corner[0][X] = stats[PX].min;
  626.       corner[0][Y] = stats[PY].min;
  627.       corner[0][Z] = stats[PZ].min;
  628.       
  629.       corner[1][X] = stats[PX].max;
  630.       corner[1][Y] = stats[PY].min;
  631.       corner[1][Z] = stats[PZ].min;
  632.       
  633.       corner[2][X] = stats[PX].min;
  634.       corner[2][Y] = stats[PY].max;
  635.       corner[2][Z] = stats[PZ].min;
  636.       
  637.       corner[3][X] = stats[PX].min;
  638.       corner[3][Y] = stats[PY].min;
  639.       corner[3][Z] = stats[PZ].max;
  640.       
  641.       /* Draw the axes */
  642.       cpack(FOREGROUND);
  643.       draw_axis(state, win, corner[0], corner[1], X);
  644.       draw_axis(state, win, corner[0], corner[2], Y);
  645.       draw_axis(state, win, corner[0], corner[3], Z);
  646.     }
  647.   
  648.   if (style & AXESSMALL) 
  649.     {
  650.       static Matrix    ident = {
  651.         {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, 
  652.         {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}
  653.       }, m;
  654.       static float vv[3];
  655.  
  656.       mmode (MPROJECTION);
  657.       getmatrix (m);
  658.       mmode (MVIEWING);
  659.       
  660.       pushmatrix();
  661.       pushviewport();
  662.       
  663.       zbuffer(FALSE);
  664.       viewport(10, 60, 10, 60);
  665.  
  666.       SetOpacity (1.0);
  667.       cpack(0xffffff);
  668.  
  669.       loadmatrix (ident);
  670.       ortho(-1.1,1.1, -1.1,1.1, -1.1,1.1);
  671.       rot(90.0-WIN_SFROM(win)[PHI]*180.0/PI,'x');
  672.       rot(-90.0-WIN_SFROM(win)[THETA]*180.0/PI,'y');
  673.       rot(-90.0, 'x');
  674.       
  675.       bgnline();
  676.       vv[0] = 0.7; vv[1] = 0.0; vv[2] = 0.0;
  677.       v3f (vv);
  678.       vv[0] = 0.0;
  679.       v3f (vv);
  680.       vv[1] = 0.7;
  681.       v3f (vv);
  682.       endline();
  683.       bgnline();
  684.       vv[0] = vv[1] = vv[2] = 0.0;
  685.       v3f (vv);
  686.       vv[2] = 0.7;
  687.       v3f (vv);
  688.       endline();
  689.       
  690.       /* Label the axes. */
  691.       cmov(0.8, 0.0, 0.0);
  692.       charstr("x");
  693.       cmov(0.0, 0.8, 0.0);
  694.       charstr("y");
  695.       cmov(0.0, 0.0, 0.8);
  696.       charstr("z");
  697.       
  698.       zbuffer(TRUE);
  699.       popviewport();
  700.       popmatrix();
  701.  
  702.       mmode (MPROJECTION);
  703.       loadmatrix (m);
  704.       mmode (MVIEWING);
  705.     }
  706.   
  707.   return ST_OKAY;
  708. }
  709.  
  710.  
  711. int draw_box_style (state_t *state, window_t *win, stats_t *stats, long style)
  712. {
  713.   if (style & (BOXWIRE | BOXSHADED | BOXSELECTED)) 
  714.     {
  715.       float mwoff;
  716.       float corner[8][DIMS];
  717.       
  718.       mwoff = win->max_width / 200.0;
  719.       corner[0][PX] = stats[PX].min - mwoff;
  720.       corner[0][PY] = stats[PY].min - mwoff;
  721.       corner[0][PZ] = stats[PZ].min - mwoff;
  722.       
  723.       corner[1][PX] = stats[PX].max + mwoff;
  724.       corner[1][PY] = stats[PY].min - mwoff;
  725.       corner[1][PZ] = stats[PZ].min - mwoff;
  726.       
  727.       corner[2][PX] = stats[PX].max + mwoff;
  728.       corner[2][PY] = stats[PY].max + mwoff;
  729.       corner[2][PZ] = stats[PZ].min - mwoff;
  730.       
  731.       corner[3][PX] = stats[PX].min - mwoff;
  732.       corner[3][PY] = stats[PY].max + mwoff;
  733.       corner[3][PZ] = stats[PZ].min - mwoff;
  734.       
  735.       corner[4][PX] = stats[PX].min - mwoff;
  736.       corner[4][PY] = stats[PY].min - mwoff;
  737.       corner[4][PZ] = stats[PZ].max + mwoff;
  738.       
  739.       corner[5][PX] = stats[PX].max + mwoff;
  740.       corner[5][PY] = stats[PY].min - mwoff;
  741.       corner[5][PZ] = stats[PZ].max + mwoff;
  742.       
  743.       corner[6][PX] = stats[PX].max + mwoff;
  744.       corner[6][PY] = stats[PY].max + mwoff;
  745.       corner[6][PZ] = stats[PZ].max + mwoff;
  746.       
  747.       corner[7][PX] = stats[PX].min - mwoff;
  748.       corner[7][PY] = stats[PY].max + mwoff;
  749.       corner[7][PZ] = stats[PZ].max + mwoff;
  750.     
  751.       /* BOXSHADED */
  752.       if (style & BOXSHADED) 
  753.         {
  754.           backface(TRUE);
  755.           SetOpacity(0.1);
  756.           cpack(FOREGROUND);
  757.           bgnpolygon();
  758.           v3f(corner[0]);
  759.           v3f(corner[1]);
  760.           v3f(corner[2]);
  761.           v3f(corner[3]);
  762.           endpolygon();
  763.           bgnpolygon();
  764.           v3f(corner[7]);
  765.           v3f(corner[6]);
  766.           v3f(corner[5]);
  767.           v3f(corner[4]);
  768.           endpolygon();
  769.           bgnpolygon();
  770.           v3f(corner[4]);
  771.           v3f(corner[5]);
  772.           v3f(corner[1]);
  773.           v3f(corner[0]);
  774.           endpolygon();
  775.           bgnpolygon();
  776.           v3f(corner[5]);
  777.           v3f(corner[6]);
  778.           v3f(corner[2]);
  779.           v3f(corner[1]);
  780.           endpolygon();
  781.           bgnpolygon();
  782.           v3f(corner[6]);
  783.           v3f(corner[7]);
  784.           v3f(corner[3]);
  785.           v3f(corner[2]);
  786.           endpolygon();
  787.           bgnpolygon();
  788.           v3f(corner[3]);
  789.           v3f(corner[7]);
  790.           v3f(corner[4]);
  791.           v3f(corner[0]);
  792.           endpolygon();
  793.           SetOpacity(1.0);
  794.           backface(FALSE);
  795.         }
  796.     
  797.     /* BOXWIRE */
  798.     if (style & BOXWIRE) 
  799.       {
  800.         cpack(FOREGROUND);
  801.         bgnline();
  802.         v3f(corner[0]);
  803.         v3f(corner[1]);
  804.         v3f(corner[2]);
  805.         v3f(corner[3]);
  806.         v3f(corner[0]);
  807.         v3f(corner[4]);
  808.         v3f(corner[5]);
  809.         v3f(corner[6]);
  810.         v3f(corner[7]);
  811.         v3f(corner[4]);
  812.         endline();
  813.         bgnline();
  814.         v3f(corner[1]);
  815.         v3f(corner[5]);
  816.         endline();
  817.         bgnline();
  818.         v3f(corner[2]);
  819.         v3f(corner[6]);
  820.         endline();
  821.         bgnline();
  822.         v3f(corner[3]);
  823.         v3f(corner[7]);
  824.         endline();
  825.       }
  826.       
  827.     /* BOXSELECTED */
  828.     if (style & BOXSELECTED) 
  829.       {
  830.         SetOpacity(0.2);
  831.         cpack(FOREGROUND);
  832.         bgnpolygon();
  833.         v3f(corner[0]);
  834.         v3f(corner[1]);
  835.         v3f(corner[2]);
  836.         v3f(corner[3]);
  837.         endpolygon();
  838.         bgnpolygon();
  839.         v3f(corner[7]);
  840.         v3f(corner[6]);
  841.         v3f(corner[5]);
  842.         v3f(corner[4]);
  843.         endpolygon();
  844.         bgnpolygon();
  845.         v3f(corner[4]);
  846.         v3f(corner[5]);
  847.         v3f(corner[1]);
  848.         v3f(corner[0]);
  849.         endpolygon();
  850.         bgnpolygon();
  851.         v3f(corner[5]);
  852.         v3f(corner[6]);
  853.         v3f(corner[2]);
  854.         v3f(corner[1]);
  855.         endpolygon();
  856.         bgnpolygon();
  857.         v3f(corner[6]);
  858.         v3f(corner[7]);
  859.         v3f(corner[3]);
  860.         v3f(corner[2]);
  861.         endpolygon();
  862.         bgnpolygon();
  863.         v3f(corner[3]);
  864.         v3f(corner[7]);
  865.         v3f(corner[4]);
  866.         v3f(corner[0]);
  867.         endpolygon();
  868.         SetOpacity(1.0);
  869.       }
  870.       
  871.     }
  872.   
  873.   return ST_OKAY;
  874. }
  875.  
  876.  
  877. int draw_box (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
  878. {
  879.   return draw_box_style(state, win, obj->stats[0], BOXSELECTED | BOXWIRE);
  880. }
  881.  
  882.  
  883. int draw_obj_recurs (state_t *state, window_t *win, object_t *obj, 
  884.                      objinfo_t *info)
  885. {
  886.   objinfo_t        local_info;
  887.   object_t        *child;
  888.   
  889.   /* If we don't need to draw this object tree, then return. */
  890.   if (obj->type & INACTIVE)
  891.     return ST_OKAY;
  892.   
  893.   /* Save the current transformation matrix context, since update_info */
  894.   /* may change it and the recursive drawing steps will want to use */
  895.   /* it. */
  896.   pushmatrix();
  897.   pushattributes();
  898.   
  899.   /* Process the new attributes and transformations to develop a new */
  900.   /* local info block.  Update only those fields that have new values. */
  901.   update_info(state, info, obj->info, &local_info);
  902.   
  903.   /* Using this information, either draw the object or decompose it */
  904.   /* further. */
  905.   if (obj->type & ATOM) 
  906.     {
  907.       /* Go ahead and draw objects using the currently active draw */
  908.       /* function */
  909.       if ((win->use_fastdraw) && (WIN_FASTDRAW_FN(win) != NULL))
  910.         WIN_FASTDRAW(win)(state, win, obj, info);
  911.       else 
  912.         {
  913.           if (local_info.draw_fn != NULL)
  914.             (*local_info.draw_fn)(state, win, obj, info);
  915.         }
  916.     }
  917.   else if (obj->type & OBJECT) 
  918.     {
  919.       /* Recursively examine all the objects in the group. */
  920.       for (child = obj->u.grp.children; child != NULL;
  921.            child = child->sibling)
  922.         {
  923.           if (draw_obj_recurs(state, win, child, &local_info) != ST_OKAY) 
  924.             {
  925.               popattributes();
  926.               popmatrix();
  927.               return ST_ERROR;
  928.             }
  929.         }
  930.     }
  931.   else 
  932.     {
  933.       bprintf
  934.         (state, "[draw_obj_recurs] SYSTEM ERROR:  Object type not defined.\n");
  935.       popattributes();
  936.       popmatrix();
  937.       return ST_ERROR;
  938.     }
  939.   
  940.   /* Draw any overlays that are requested for this object. */
  941.   /* FOCUS POINT */
  942.   if (local_info.hereonly.value & FOCUSPOINT) 
  943.     {
  944.       float cx, cy, cz;
  945.       float size;
  946.       
  947.       /* Get the center of the FOCUSPOINT "jack" and choose a size */
  948.       /* for it. */
  949.       cx = WIN_AT(win)[X];
  950.       cy = WIN_AT(win)[Y];
  951.       cz = WIN_AT(win)[Z];
  952.       size = WIN_MAXWIDTH(win) / 200.0;
  953.       
  954.       cpack(FOREGROUND);
  955.       /* Draw x-axis arm. */
  956.       bgnline();
  957.       v3f(p3f(cx-size, cy, cz));
  958.       v3f(p3f(cx+size, cy, cz));
  959.       endline();
  960.       /* Draw y-axis arm. */
  961.       bgnline();
  962.       v3f(p3f(cx, cy-size, cz));
  963.       v3f(p3f(cx, cy+size, cz));
  964.       endline();
  965.       /* Draw z-axis arm. */
  966.       bgnline();
  967.       v3f(p3f(cx, cy, cz-size));
  968.       v3f(p3f(cx, cy, cz+size));
  969.       endline();
  970.     }
  971.  
  972.   /* AXES */
  973.   if (local_info.hereonly.value & (AXESSMALL|AXESLARGE))
  974.     draw_axes(state, win, obj, info, local_info.hereonly.value);
  975.   
  976.   /* GRID */
  977.   if (local_info.hereonly.value & GRIDXY)
  978.     draw_grid(state, win, obj, info, GRIDXY);
  979.   if (local_info.hereonly.value & GRIDXZ)
  980.     draw_grid(state, win, obj, info, GRIDXZ);
  981.   if (local_info.hereonly.value & GRIDYZ)
  982.     draw_grid(state, win, obj, info, GRIDYZ);
  983.   
  984.   /* SCATTER */
  985.   if (local_info.heredown.value & SCATXY)
  986.     draw_scatter(state, win, obj, local_info.draw_fn, info, SCATXY);
  987.   if (local_info.heredown.value & SCATXZ)
  988.     draw_scatter(state, win, obj, local_info.draw_fn, info, SCATXZ);
  989.   if (local_info.heredown.value & SCATYZ)
  990.     draw_scatter(state, win, obj, local_info.draw_fn, info, SCATYZ);
  991.   
  992.   /* BOUNDING BOX */
  993.   /* Bounding box for the entire dataset over time. */
  994.   if (local_info.hereonly.value & (BOXWIRE | BOXSHADED))
  995.     draw_box_style(state, win, win->stats[0],
  996.                    local_info.hereonly.value & (BOXWIRE | BOXSHADED));
  997.     
  998.   if ((obj != NULL) && (OBJ_INFO(obj) != NULL) &&
  999.       (OBJ_PICKMODE(obj) == PICK_OBJECT))
  1000.     draw_box_style(state, win, obj->stats[0], (BOXSELECTED | BOXWIRE));
  1001.   
  1002.   /* Restore the transformation matrix. */
  1003.   popattributes();
  1004.   popmatrix();
  1005.   return ST_OKAY;
  1006. }
  1007.  
  1008.  
  1009. /* update info copies the oldinfo record into the newinfo record, then */
  1010. /* updates newinfo fields with new information from the updinfo record. */
  1011. /* Only fields which have changed in updinfo are used.  If no errors */
  1012. /* occur, the function returns ST_OKAY. */
  1013. int update_info(state_t *state, objinfo_t *oldinfo, objinfo_t *updinfo,
  1014.                 objinfo_t *newinfo)
  1015. {
  1016.   /* At the very least, the new information is the same as the old. */
  1017.   memcpy((void *) newinfo, (void *) oldinfo, (size_t) sizeof(objinfo_t));
  1018.   
  1019.   /* If the update information pointer is NULL, no changes are being */
  1020.   /* made. */
  1021.   if (updinfo == NULL)
  1022.     return ST_OKAY;
  1023.   
  1024.   /* Update changed fields in the newinfo record from updinfo. */
  1025.   if (updinfo->scl.used) 
  1026.     {
  1027.       newinfo->scl.coord[X] = updinfo->scl.coord[X];
  1028.       newinfo->scl.coord[Y] = updinfo->scl.coord[Y];
  1029.       newinfo->scl.coord[Z] = updinfo->scl.coord[Z];
  1030.       newinfo->scl.used = TRUE;
  1031.       
  1032.       /* Add the scaling to the transformation matrix. */
  1033.       scale(updinfo->scl.coord[X], updinfo->scl.coord[Y],
  1034.             updinfo->scl.coord[Z]);
  1035.     }
  1036.   else 
  1037.     {
  1038.       newinfo->scl.used = FALSE;
  1039.     }
  1040.   
  1041.   if (updinfo->rot.used) 
  1042.     {
  1043.       newinfo->rot.coord[PHI] = updinfo->rot.coord[PHI];
  1044.       newinfo->rot.coord[THETA] = updinfo->rot.coord[THETA];
  1045.       newinfo->rot.used = TRUE;
  1046.       
  1047.       /* Add the rotation to the transformation matrix. */
  1048.       rot(updinfo->rot.coord[PHI], 'y');
  1049.       rot(updinfo->rot.coord[THETA], 'z');
  1050.     }
  1051.   else 
  1052.     {
  1053.       newinfo->rot.used = FALSE;
  1054.     }
  1055.   
  1056.   if (updinfo->trn.used) 
  1057.     {
  1058.       newinfo->trn.coord[X] = updinfo->trn.coord[X];
  1059.       newinfo->trn.coord[Y] = updinfo->trn.coord[Y];
  1060.       newinfo->trn.coord[Z] = updinfo->trn.coord[Z];
  1061.       newinfo->trn.used = TRUE;
  1062.       
  1063.       translate(updinfo->trn.coord[X], updinfo->trn.coord[Y],
  1064.                 updinfo->trn.coord[Z]);
  1065.     }
  1066.   else 
  1067.     {
  1068.       newinfo->trn.used = FALSE;
  1069.     }
  1070.     
  1071.   if (updinfo->draw_fn != NULL)
  1072.     newinfo->draw_fn = updinfo->draw_fn;
  1073.   else
  1074.     newinfo->draw_fn = oldinfo->draw_fn;
  1075.     
  1076.   /* Do something with ATPOINT, BOXWIRE, BOXSHADED, LABELS */
  1077.   newinfo->hereonly = updinfo->hereonly;
  1078.   
  1079.   newinfo->heredown.used = TRUE;
  1080.   newinfo->heredown.value = updinfo->heredown.value | oldinfo->heredown.value;
  1081.   
  1082.   return ST_OKAY;
  1083. }
  1084.  
  1085.  
  1086. int draw_nothing (state_t *state, window_t *win, object_t *obj, 
  1087.                   objinfo_t *info)
  1088. {
  1089.   if (OBJ_PICKMODE(obj) == PICK_FACE)
  1090.     return DrawPickedFaces(state, win, obj, info);
  1091.   else if (OBJ_PICKMODE(obj) == PICK_VERTEX)
  1092.     return DrawPickedVertices(state, win, obj, info);
  1093.  
  1094.   /* This is new. */
  1095.   return ST_OKAY;
  1096. }
  1097.  
  1098.  
  1099. int draw_vertices(state_t *state, window_t *win, object_t *obj, 
  1100.                   objinfo_t *info)
  1101. {
  1102.   float    jackscale;
  1103.   long    count;
  1104.   
  1105.   Vdata_t **vdata;
  1106.   Vdata_t *vcolor_v;
  1107.   Vdata_t *pcoord_v;
  1108.   
  1109.   float    (*pcoord)[DIMS];
  1110.   int *vcolor;
  1111.   char *picked;
  1112.  
  1113.   int single_color;
  1114.   
  1115.   /* Get pointers to the pertinent data sets */
  1116.   vdata = obj->u.obj.vdata;
  1117.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  1118.   if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  1119.     return ST_OKAY;
  1120.  
  1121.   /* Set up the consolidated coordinate array pointer. */
  1122.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  1123.   count = pcoord_v->stats[0].rec_count;
  1124.   assert (pcoord_v->stats[0].type == PVFLOAT);
  1125.  
  1126.   /* Get a pointer to the pick list if the object is picked and it */
  1127.   /* is in the proper mode. */
  1128.   picked = OBJ_PICKLIST(obj);
  1129.   if (OBJ_PICKMODE(obj) != PICK_VERTEX)
  1130.     picked = NULL;
  1131.   if (OBJ_PICKMODE(obj) == PICK_FACE)
  1132.     DrawPickedFaces(state, win, obj, info);
  1133.   
  1134.   if (FEQ(win->sphere_size, 0.0))
  1135.     {
  1136.       /* If there is no vertex color information, draw without it */
  1137.       /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  1138.       jackscale = win->max_width / 100.0;
  1139.       if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1140.         {
  1141.           cpack(FOREGROUND);
  1142.           
  1143.           /* No color information.  Use foreground and draw the */
  1144.           /* appropriate shapes. */
  1145.           bgnpoint();
  1146.           while (count > 0) 
  1147.             {
  1148.               if (picked && *picked) 
  1149.                 { /* selected */
  1150.                   endpoint();
  1151.                   DrawJack(pcoord, jackscale);
  1152.                   bgnpoint();
  1153.                 }
  1154.               else 
  1155.                 { /* not selected */
  1156.                   v3f(*pcoord);
  1157.                   
  1158.                   if (!(count & 255)) 
  1159.                     {
  1160.                       endpoint();
  1161.                       bgnpoint();
  1162.                     }
  1163.                 }
  1164.               
  1165.               /* Move to the next x, y, z set and decrement the */
  1166.               /* count. */
  1167.               if (picked) 
  1168.                 picked++;
  1169.               pcoord++;
  1170.               count--;
  1171.             }
  1172.           endpoint();
  1173.         }
  1174.       else 
  1175.         {
  1176.           /* Set pointers to the actual data and the size of the data */
  1177.           /* sets. */
  1178.           assert (vcolor_v->stats[0].type == PVINTEGER);
  1179.           
  1180.           /* There is color information.  Get it and use it to draw the */
  1181.           /* appropriate shapes. */
  1182.           vcolor = (int *) vcolor_v->data;
  1183.           bgnpoint();
  1184.           while (count > 0) 
  1185.             {
  1186.               if (picked && *picked) 
  1187.                 { /* selected */
  1188.                   endpoint();
  1189.                   cpack(FOREGROUND);
  1190.                   DrawJack(pcoord, jackscale);
  1191.                   bgnpoint();
  1192.                 }
  1193.               else 
  1194.                 { /* not selected */
  1195.                   PALETTECPACK(*vcolor);
  1196.                   v3f(*pcoord);
  1197.                   
  1198.                   if (!(count & 255)) 
  1199.                     {
  1200.                       endpoint();
  1201.                       bgnpoint();
  1202.                     }
  1203.                 }
  1204.               
  1205.               /* Move to the next x, y, z set, color entry, and */
  1206.               /* decrement the count. */
  1207.               if (picked) 
  1208.                 picked++;
  1209.               pcoord++;
  1210.               vcolor++;
  1211.               count--;
  1212.             }
  1213.           endpoint();
  1214.         }
  1215.     }
  1216.   else
  1217.     {
  1218.       /* If there is no vertex color information, draw without it */
  1219.       /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  1220.       jackscale = win->max_width / 100.0;
  1221.  
  1222.       /* Set sphere mode. */
  1223.       sphmode (SPH_DEPTH, win->sphere_depth);
  1224.       sphmode (SPH_TESS, SPH_CUBE);
  1225.  
  1226.       /* Backfacing is safe since we're spheres. */
  1227.       backface (TRUE);
  1228.  
  1229.       /* Turn on lighting if appropriate. */
  1230.       if (WIN_LIGHT(win))
  1231.         lighting_on (state, win, 
  1232.                      WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
  1233.       
  1234.       if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1235.         {
  1236.           cpack(FOREGROUND);
  1237.  
  1238.           /* No color information.  Use foreground and draw the */
  1239.           /* appropriate shapes. */
  1240.           while (count > 0) 
  1241.             {
  1242.               if (picked && *picked) 
  1243.                 { /* selected */
  1244.                   DrawJack(pcoord, jackscale);
  1245.                 }
  1246.               else 
  1247.                 { /* not selected */
  1248.                   float params[4];
  1249.                   
  1250.                   params[0] = (*pcoord)[0];
  1251.                   params[1] = (*pcoord)[1];
  1252.                   params[2] = (*pcoord)[2];
  1253.                   params[3] = win->sphere_size;
  1254.                   
  1255.                   sphdraw (params);
  1256.                 }
  1257.               
  1258.               /* Move to the next x, y, z set and decrement the */
  1259.               /* count. */
  1260.               if (picked) picked++;
  1261.               pcoord++;
  1262.               count--;
  1263.             }
  1264.         }
  1265.       else 
  1266.         {
  1267.           /* Set pointers to the actual data and the size of the data */
  1268.           /* sets. */
  1269.           assert (vcolor_v->stats[0].type == PVINTEGER);
  1270.           
  1271.           /* There is color information.  Get it and use it to draw the */
  1272.           /* appropriate shapes. */
  1273.           vcolor = (int *) vcolor_v->data;
  1274.           
  1275.           /* Look to see if we've got a one-color palette.  Right
  1276.              now we look for the unlikely event that state->pal[69] =
  1277.              state->pal[149] = state->pal[219]. */
  1278.           if (state->pal[69][R]  == state->pal[149][R] &&
  1279.               state->pal[149][R] == state->pal[219][R] &&
  1280.               state->pal[69][G]  == state->pal[149][G] &&
  1281.               state->pal[149][G] == state->pal[219][G] &&
  1282.               state->pal[0][B]   == state->pal[255][B] &&
  1283.               state->pal[1][R]   == state->pal[254][R] &&
  1284.               state->pal[10][G]  == state->pal[245][G])
  1285.             {
  1286.               single_color = 1;
  1287.               PALETTECPACK(69);
  1288.             }
  1289.           else
  1290.             single_color = 0;
  1291.           
  1292.           while (count > 0) 
  1293.             {
  1294.               if (picked && *picked) 
  1295.                 { /* selected */
  1296.                   cpack(FOREGROUND);
  1297.                   DrawJack(pcoord, jackscale);
  1298.                   if (single_color)
  1299.                     PALETTECPACK(69);
  1300.                 }
  1301.               else 
  1302.                 { /* not selected */
  1303.                   float params[4];
  1304.                   
  1305.                   if (!single_color)
  1306.                     PALETTECPACK(*vcolor);
  1307.                   
  1308.                   params[0] = (*pcoord)[0];
  1309.                   params[1] = (*pcoord)[1];
  1310.                   params[2] = (*pcoord)[2];
  1311.                   params[3] = win->sphere_size;
  1312.                   
  1313.                   sphdraw (params);      
  1314.                 }
  1315.               /* Move to the next x, y, z set, color entry, and */
  1316.               /* decrement the count. */
  1317.               if (picked) picked++;
  1318.               pcoord++;
  1319.               vcolor++;
  1320.               count--;
  1321.             }
  1322.         }
  1323.  
  1324.       /* Turn off lighting if it's on. */
  1325.       if (WIN_LIGHT(win))
  1326.         lighting_off ();
  1327.  
  1328.       backface(FALSE);
  1329.     }
  1330.   
  1331.   return ST_OKAY;
  1332. }
  1333.  
  1334.  
  1335. int draw_edges (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
  1336. {
  1337.   long count;
  1338.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  1339.   float (*pcoord)[DIMS];
  1340.   int *vcolor, *connect;
  1341.   char *picked;
  1342.   int i, nvert, vertex;
  1343.  
  1344.   linewidth (win->line_width);
  1345.  
  1346.   /* Get pointers to the pertinent data sets */
  1347.   vdata = obj->u.obj.vdata;
  1348.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  1349.   if ((connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  1350.     if ((connect_v = get_vdata(state, vdata[MCONNECT])) == NULL) 
  1351.       {
  1352.         draw_vertices(state, win, obj, info);
  1353.         return ST_OKAY;
  1354.       }
  1355.   if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  1356.     return ST_OKAY;
  1357.   
  1358.   /* Collect connectivity information for drawing. */
  1359.   connect = (int *) connect_v->data;
  1360.   count = connect_v->stats[0].rec_count;
  1361.   nvert = connect_v->stats[0].rec_size;
  1362.     
  1363.   /* Set up the consolidated coordinate array pointer. */
  1364.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  1365.   assert (pcoord_v->stats[0].type == PVFLOAT);
  1366.   
  1367.   /* Get a pointer to the pick list if the object is picked and it */
  1368.   /* is in the proper mode. */
  1369.   picked = OBJ_PICKLIST(obj);
  1370.   if (OBJ_PICKMODE(obj) != PICK_FACE)
  1371.     picked = NULL;
  1372.   if (OBJ_PICKMODE(obj) == PICK_VERTEX)
  1373.     DrawPickedVertices(state, win, obj, info);
  1374.     
  1375.   /* If there is no vertex color information, draw without it */
  1376.   /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  1377.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1378.     {
  1379.       cpack(FOREGROUND);
  1380.       
  1381.       /* No color information.  Use foreground and draw the */
  1382.       /* appropriate shapes. */
  1383.       while (count > 0) 
  1384.         {
  1385.           if (picked && *picked)
  1386.             bgnpolygon();
  1387.           else 
  1388.             bgnclosedline();
  1389.           
  1390.           for (i = nvert; i > 0; i--) 
  1391.             {
  1392.               if ( (vertex = *(connect++)-1) == -1) 
  1393.                 {
  1394.                   connect += i-1;
  1395.                   break;
  1396.                 }
  1397.               v3f(pcoord[vertex]);
  1398.             }
  1399.           if (picked && *picked)
  1400.             endpolygon();
  1401.           else 
  1402.             endclosedline();
  1403.           
  1404.           if (picked) 
  1405.             picked++;
  1406.           count--;
  1407.         }
  1408.     }
  1409.   else 
  1410.     {
  1411.       /* Set pointers to the actual data and the size of the data */
  1412.       /* sets. */
  1413.       assert (vcolor_v->stats[0].type == PVINTEGER);
  1414.       
  1415.       /* There is color information.  Get it and use it to draw the */
  1416.       /* appropriate shapes. */
  1417.       vcolor = (int *) vcolor_v->data;
  1418.       while (count > 0) 
  1419.         {
  1420.           if (picked && *picked)
  1421.             bgnpolygon();
  1422.           else 
  1423.             bgnclosedline();
  1424.           
  1425.           for (i = nvert; i > 0; i--) 
  1426.             {
  1427.               if ( (vertex = *(connect++)-1) == -1) 
  1428.                 {
  1429.                   connect += i-1;
  1430.                   break;
  1431.                 }
  1432.               
  1433.               PALETTECPACK(vcolor[vertex]);
  1434.               v3f(pcoord[vertex]);
  1435.             }
  1436.           
  1437.           if (picked && *picked)
  1438.             endpolygon();
  1439.           else 
  1440.             endclosedline();
  1441.           
  1442.           if (picked) picked++;
  1443.           count--;
  1444.         }
  1445.     }
  1446.  
  1447.   linewidth (1);
  1448.   return ST_OKAY;
  1449. }
  1450.  
  1451.  
  1452. int DrawTrans (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
  1453. {
  1454.   /* Set the opacity level to one-half. */
  1455.   SetOpacity(0.5);
  1456.   
  1457.   /* Draw the object as faces. */
  1458.   draw_faces(state, win, obj, info);
  1459.   
  1460.   /* Restore objects to full-opacity. */
  1461.   SetOpacity(1.0);
  1462.   return ST_OKAY;
  1463. }
  1464.  
  1465.  
  1466. int draw_faces (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
  1467. {
  1468.   long count;
  1469.   
  1470.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  1471.     
  1472.   float    (*pcoord)[DIMS];
  1473.   int *vcolor, *connect;
  1474.   char *picked;
  1475.   
  1476.   int i, nvert, vertex, single_color;
  1477.   
  1478.   /* Get pointers to the pertinent data sets */
  1479.   vdata = obj->u.obj.vdata;
  1480.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  1481.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
  1482.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
  1483.       return draw_vertices(state, win, obj, info);
  1484.   
  1485.   /* If the plist does not describe polygons, draw edges. */
  1486.   if (connect_v->stats[0].rec_size < 3)
  1487.     return draw_edges(state, win, obj, info);
  1488.   
  1489.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  1490.     return ST_OKAY;
  1491.   
  1492.   /* Collect connectivity information for drawing. */
  1493.   connect = (int *) connect_v->data;
  1494.   count = connect_v->stats[0].rec_count;
  1495.   nvert = connect_v->stats[0].rec_size;
  1496.   
  1497.   /* Set up the consolidated coordinate array pointer. */
  1498.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  1499.   assert (pcoord_v->stats[0].type == PVFLOAT);
  1500.   
  1501.   /* Get a pointer to the pick list if the object is picked and it */
  1502.   /* is in the proper mode. */
  1503.   picked = OBJ_PICKLIST(obj);
  1504.   if (OBJ_PICKMODE(obj) != PICK_FACE)
  1505.     picked = NULL;
  1506.   if (OBJ_PICKMODE(obj) == PICK_VERTEX)
  1507.     DrawPickedVertices(state, win, obj, info);
  1508.   
  1509.   /* If there is no vertex color information, draw without it */
  1510.   /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  1511.  
  1512.   /* Turn on lighting if appropriate. */
  1513.   if (WIN_LIGHT(win))
  1514.     lighting_on (state, win, 
  1515.                  WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
  1516.   
  1517.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1518.     {
  1519.       cpack(FOREGROUND);
  1520.       /* No color information.  Use foreground and draw the */
  1521.       /* appropriate shapes. */
  1522.       while (count > 0) 
  1523.         {
  1524.           /* If lighting is on, find a normal for the polygon. */
  1525.           if (WIN_LIGHT(win))
  1526.             {
  1527.               find_normal(pcoord[*(connect)-1], pcoord[*(connect+1)-1], 
  1528.                           pcoord[*(connect+2)-1]);
  1529.               n3f (nn);
  1530.             }
  1531.  
  1532.           bgnpolygon();
  1533.           for (i = nvert; i > 0; i--) 
  1534.             {
  1535.               if ( (vertex = *(connect++)-1) == -1) 
  1536.                 {
  1537.                   connect += i-1;
  1538.                   break;
  1539.                 }
  1540.               v3f(pcoord[vertex]);
  1541.             }
  1542.           endpolygon();
  1543.           
  1544.           if (picked) 
  1545.             picked++;
  1546.           count--;
  1547.         }
  1548.     }
  1549.   else 
  1550.     {
  1551.       /* Set pointers to the actual data and the size of the data */
  1552.       /* sets. */
  1553.       assert (vcolor_v->stats[0].type == PVINTEGER);
  1554.       
  1555.       /* There is color information.  Get it and use it to draw the */
  1556.       /* appropriate shapes. */
  1557.       vcolor = (int *) vcolor_v->data;
  1558.  
  1559.       /* Look to see if we've got a one-color palette.  Right
  1560.          now we look for the unlikely event that pal[69] =
  1561.          pal[149] = pal[219]. */
  1562.       if (state->pal[69][R]  == state->pal[149][R] &&
  1563.           state->pal[149][R] == state->pal[219][R] &&
  1564.           state->pal[69][G]  == state->pal[149][G] &&
  1565.           state->pal[149][G] == state->pal[219][G] &&
  1566.           state->pal[0][B]   == state->pal[255][B] &&
  1567.           state->pal[1][R]   == state->pal[254][R] &&
  1568.           state->pal[10][G]  == state->pal[245][G])
  1569.         {
  1570.           single_color = 1;
  1571.           PALETTECPACK(69);
  1572.         }
  1573.       else
  1574.         single_color = 0;
  1575.  
  1576.       while (count > 0) 
  1577.         {
  1578.           /* If lighting is on, find a normal for the polygon. */
  1579.           if (WIN_LIGHT(win))
  1580.             {
  1581.               find_normal(pcoord[*(connect)-1], pcoord[*(connect+1)-1], 
  1582.                           pcoord[*(connect+2)-1]);
  1583.               n3f (nn);
  1584.             }
  1585.  
  1586.           bgnpolygon();
  1587.           for (i = nvert; i > 0; i--) 
  1588.             {
  1589.               if ((vertex = *(connect++)-1) == -1) 
  1590.                 {
  1591.                   connect += i-1;
  1592.                   break;
  1593.                 }
  1594.               
  1595.               if (picked && *picked)
  1596.                 cpack(FOREGROUND);
  1597.               else
  1598.                 {
  1599.                   if (!single_color)
  1600.                     PALETTECPACK(vcolor[vertex]);
  1601.                 }
  1602.               v3f(pcoord[vertex]);
  1603.               if (single_color && picked && *picked)
  1604.                 PALETTECPACK(69);
  1605.             }
  1606.           endpolygon();
  1607.           
  1608.           if (picked) picked++;
  1609.           count--;
  1610.         }
  1611.  
  1612.     }
  1613.   /* Turn off lighting if it's on. */
  1614.   if (WIN_LIGHT(win))
  1615.     lighting_off ();
  1616.   
  1617.   return ST_OKAY;
  1618. }
  1619.  
  1620.  
  1621. int draw_outlined_faces(state_t *state, window_t *win, object_t *obj,
  1622.                         objinfo_t *info)
  1623. {
  1624.   long count;
  1625.   
  1626.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  1627.   
  1628.   float (*pcoord)[DIMS];
  1629.   float pcoord_outline[DIMS];
  1630.   int *vcolor, *connect, *oconnect;
  1631.   char *picked;
  1632.   int i, j, nvert, vertex, single_color;
  1633.  
  1634.   /* Get pointers to the pertinent data sets */
  1635.   vdata = obj->u.obj.vdata;
  1636.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  1637.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  1638.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL) 
  1639.       return draw_vertices(state, win, obj, info);
  1640.   /* If the plist does not describe polygons, draw edges. */
  1641.   if (connect_v->stats[0].rec_size < 3)
  1642.     return draw_edges(state, win, obj, info);
  1643.   
  1644.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  1645.     return ST_OKAY;
  1646.   
  1647.   /* Collect connectivity information for drawing. */
  1648.   oconnect = connect = (int *) connect_v->data;
  1649.   count = connect_v->stats[0].rec_count;
  1650.   nvert = connect_v->stats[0].rec_size;
  1651.     
  1652.   /* Set up the consolidated coordinate array pointer. */
  1653.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  1654.  
  1655.   assert (pcoord_v->stats[0].type == PVFLOAT);
  1656.   
  1657.   /* Get a pointer to the pick list if the object is picked and it */
  1658.   /* is in the proper mode. */
  1659.   picked = OBJ_PICKLIST(obj);
  1660.   if (OBJ_PICKMODE(obj) != PICK_FACE)
  1661.     picked = NULL;
  1662.   if (OBJ_PICKMODE(obj) == PICK_VERTEX)
  1663.     DrawPickedVertices(state, win, obj, info);
  1664.  
  1665.   linewidth(win->line_width);
  1666.  
  1667.   /* Set up the squeezed zbuffer. */
  1668.   grok_squeezed_zbuffer (state, win);
  1669.   
  1670.   /* If there is no vertex color information, draw without it. */
  1671.   /* Otherwise, grab the color array. */
  1672.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1673.     {
  1674.       /* Turn on lighting if appropriate. */
  1675.       if (WIN_LIGHT(win))
  1676.         lighting_on (state, win, 
  1677.                      WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
  1678.  
  1679.       while (count > 0)
  1680.         {
  1681.           /* Set one normal for the whole damn thing. */
  1682.           if (WIN_LIGHT(win))
  1683.             {
  1684.               find_normal(pcoord[*(connect)-1],
  1685.                           pcoord[*(connect+1)-1], pcoord[*(connect+2)-1]);
  1686.               n3f (nn);
  1687.             }
  1688.  
  1689.           if (picked && *picked) 
  1690.             {
  1691.               cpack(FOREGROUND);
  1692.               bgnpolygon();
  1693.               for (i = nvert; i > 0; i--) 
  1694.                 {
  1695.                   if ( (vertex = *(connect++)-1) == -1) 
  1696.                     {
  1697.                       connect += i-1;
  1698.                       break;
  1699.                     }
  1700.                   v3f(pcoord[vertex]);
  1701.                 }
  1702.               endpolygon();
  1703.             }
  1704.           else 
  1705.             {
  1706.               /* Save connectivity pointer. */
  1707.               oconnect = connect;
  1708.  
  1709.               /* Draw the polygon. */
  1710.               cpack (0xffffff);
  1711.               bgnpolygon();
  1712.               for (i = nvert; i > 0; i--) 
  1713.                 {
  1714.                   if ( (vertex = *(connect++)-1) == -1) 
  1715.                     {
  1716.                       connect += i-1;
  1717.                       break;
  1718.                     }
  1719.                   
  1720.                   v3f(pcoord[vertex]);
  1721.                 }
  1722.               endpolygon();
  1723.  
  1724.               /* Start connectivity anew. */
  1725.               connect = oconnect;
  1726.  
  1727.               /* Squeeze the zbuffer. */
  1728.               set_squeezed_zbuffer ();
  1729.  
  1730.               /* Draw the outline of the polygon, with Z values */
  1731.               cpack(WIN_OUTLINE_COLOR(win));
  1732.               bgnclosedline();
  1733.               for (i = nvert; i > 0; i--) 
  1734.                 {
  1735.                   if ( (vertex = *(connect++)-1) == -1)
  1736.                     {
  1737.                       connect += i-1;
  1738.                       break;
  1739.                     }
  1740.                   v3f(pcoord[vertex]); 
  1741.                 }
  1742.               endclosedline();
  1743.  
  1744.               /* Restore the Zbuffer. */
  1745.               lsetdepth (gstate->zmax, gstate->zmin);
  1746.  
  1747.             }
  1748.           
  1749.           if (picked) picked++;
  1750.           count--;
  1751.         }
  1752.  
  1753.       /* Turn off lighting if it's on. */
  1754.       if (WIN_LIGHT(win))
  1755.         lighting_off ();
  1756.       
  1757.     }
  1758.   else 
  1759.     {
  1760.       /* Set pointers to the actual data and the size of the data */
  1761.       /* sets. */
  1762.       assert (vcolor_v->stats[0].type == PVINTEGER);
  1763.       
  1764.       /* There is color information.  Get it and use it to draw the */
  1765.       /* appropriate shapes. */
  1766.       vcolor = (int *) vcolor_v->data;
  1767.  
  1768.       /* Turn on lighting if appropriate. */
  1769.       if (WIN_LIGHT(win))
  1770.         lighting_on (state, win, 
  1771.                      WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
  1772.  
  1773.       while (count > 0) 
  1774.         {
  1775.           /* Set one normal for the whole damn thing. */
  1776.           if (WIN_LIGHT(win))
  1777.             {
  1778.               find_normal(pcoord[*(connect)-1],
  1779.                           pcoord[*(connect+1)-1], pcoord[*(connect+2)-1]);
  1780.               n3f (nn);
  1781.             }
  1782.  
  1783.           if (picked && *picked) 
  1784.             {
  1785.               bgnpolygon();
  1786.               for (i = nvert; i > 0; i--) 
  1787.                 {
  1788.                   if ( (vertex = *(connect++)-1) == -1) 
  1789.                     {
  1790.                       connect += i-1;
  1791.                       break;
  1792.                     }
  1793.                   PALETTECPACK(vcolor[vertex]);
  1794.                   v3f(pcoord[vertex]);
  1795.                 }
  1796.               endpolygon();
  1797.             }
  1798.           else 
  1799.             {
  1800.               /* Save connectivity pointer. */
  1801.               oconnect = connect;
  1802.  
  1803.               /* Draw the polygon. */
  1804.               bgnpolygon();
  1805.               for (i = nvert; i > 0; i--) 
  1806.                 {
  1807.                   if ( (vertex = *(connect++)-1) == -1) 
  1808.                     {
  1809.                       connect += i-1;
  1810.                       break;
  1811.                     }
  1812.                   
  1813.                   PALETTECPACK(vcolor[vertex]);
  1814.                   v3f(pcoord[vertex]);
  1815.                 }
  1816.               endpolygon();
  1817.  
  1818.               /* Start connectivity anew. */
  1819.               connect = oconnect;
  1820.  
  1821.               /* Squeeze the zbuffer. */
  1822.               set_squeezed_zbuffer ();
  1823.  
  1824.               /* Draw the outline of the polygon, with Z values */
  1825.               cpack(WIN_OUTLINE_COLOR(win));
  1826.               bgnclosedline();
  1827.               for (i = nvert; i > 0; i--) 
  1828.                 {
  1829.                   if ( (vertex = *(connect++)-1) == -1)
  1830.                     {
  1831.                       connect += i-1;
  1832.                       break;
  1833.                     }
  1834.                   v3f(pcoord[vertex]); 
  1835.                 }
  1836.               endclosedline();
  1837.  
  1838.               /* Restore the Zbuffer. */
  1839.               lsetdepth (gstate->zmax, gstate->zmin);
  1840.               
  1841.             }          
  1842.           if (picked) picked++;
  1843.           count--;
  1844.         }
  1845.       
  1846.       /* Turn off lighting if it's on. */
  1847.       if (WIN_LIGHT(win))
  1848.         lighting_off ();
  1849.     }
  1850.  
  1851.   linewidth (1);
  1852.   
  1853.   return ST_OKAY;
  1854. }
  1855.  
  1856.  
  1857. int draw_hidden_edges(state_t *state, window_t *win, object_t *obj,
  1858.                       objinfo_t *info)
  1859. {
  1860.   long count;
  1861.   
  1862.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  1863.   
  1864.   float (*pcoord)[DIMS];
  1865.   float pcoord_outline[DIMS];
  1866.   int *vcolor, *connect, *oconnect;
  1867.   char *picked;
  1868.   int i, j, nvert, vertex, single_color;
  1869.  
  1870.   /* Get pointers to the pertinent data sets */
  1871.   vdata = obj->u.obj.vdata;
  1872.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  1873.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  1874.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL) 
  1875.       return draw_vertices(state, win, obj, info);
  1876.   /* If the plist does not describe polygons, draw edges. */
  1877.   if (connect_v->stats[0].rec_size < 3)
  1878.     return draw_edges(state, win, obj, info);
  1879.   
  1880.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  1881.     return ST_OKAY;
  1882.   
  1883.   /* Collect connectivity information for drawing. */
  1884.   oconnect = connect = (int *) connect_v->data;
  1885.   count = connect_v->stats[0].rec_count;
  1886.   nvert = connect_v->stats[0].rec_size;
  1887.     
  1888.   /* Set up the consolidated coordinate array pointer. */
  1889.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  1890.  
  1891.   assert (pcoord_v->stats[0].type == PVFLOAT);
  1892.   
  1893.   /* Get a pointer to the pick list if the object is picked and it */
  1894.   /* is in the proper mode. */
  1895.   picked = OBJ_PICKLIST(obj);
  1896.   if (OBJ_PICKMODE(obj) != PICK_FACE)
  1897.     picked = NULL;
  1898.   if (OBJ_PICKMODE(obj) == PICK_VERTEX)
  1899.     DrawPickedVertices(state, win, obj, info);
  1900.  
  1901.   linewidth(win->line_width);
  1902.   
  1903.   /* Set up the squeezed zbuffer. */
  1904.   grok_squeezed_zbuffer (state, win);
  1905.   
  1906.   /* If there is no vertex color information, draw without it. */
  1907.   /* Otherwise, grab the color array. */
  1908.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  1909.     {
  1910.       while (count > 0)
  1911.         {
  1912.           if (picked && *picked) 
  1913.             {
  1914.               cpack(FOREGROUND);
  1915.               bgnpolygon();
  1916.               for (i = nvert; i > 0; i--) 
  1917.                 {
  1918.                   if ( (vertex = *(connect++)-1) == -1) 
  1919.                     {
  1920.                       connect += i-1;
  1921.                       break;
  1922.                     }
  1923.                   v3f(pcoord[vertex]);
  1924.                 }
  1925.               endpolygon();
  1926.             }
  1927.           else 
  1928.             {
  1929.               /* Save connectivity pointer. */
  1930.               oconnect = connect;
  1931.  
  1932.               /* Draw the polygon. */
  1933.               cpack (0);
  1934.               bgnpolygon();
  1935.               for (i = nvert; i > 0; i--) 
  1936.                 {
  1937.                   if ( (vertex = *(connect++)-1) == -1) 
  1938.                     {
  1939.                       connect += i-1;
  1940.                       break;
  1941.                     }
  1942.                   
  1943.                   v3f(pcoord[vertex]);
  1944.                 }
  1945.               endpolygon();
  1946.  
  1947.               /* Start connectivity anew. */
  1948.               connect = oconnect;
  1949.  
  1950.               /* Squeeze the zbuffer. */
  1951.               set_squeezed_zbuffer ();
  1952.  
  1953.               /* Draw the outline of the polygon, with Z values */
  1954.               cpack (FOREGROUND);
  1955.               bgnclosedline();
  1956.               for (i = nvert; i > 0; i--) 
  1957.                 {
  1958.                   if ( (vertex = *(connect++)-1) == -1)
  1959.                     {
  1960.                       connect += i-1;
  1961.                       break;
  1962.                     }
  1963.                   v3f(pcoord[vertex]); 
  1964.                 }
  1965.               endclosedline();
  1966.  
  1967.               /* Restore the Zbuffer. */
  1968.               lsetdepth (gstate->zmax, gstate->zmin);
  1969.  
  1970.             }
  1971.           
  1972.           if (picked) picked++;
  1973.           count--;
  1974.         }
  1975.  
  1976.     }
  1977.   else 
  1978.     {
  1979.       /* Set pointers to the actual data and the size of the data */
  1980.       /* sets. */
  1981.       assert (vcolor_v->stats[0].type == PVINTEGER);
  1982.       
  1983.       /* There is color information.  Get it and use it to draw the */
  1984.       /* appropriate shapes. */
  1985.       vcolor = (int *) vcolor_v->data;
  1986.  
  1987.       while (count > 0) 
  1988.         {
  1989.           if (picked && *picked) 
  1990.             {
  1991.               bgnpolygon();
  1992.               for (i = nvert; i > 0; i--) 
  1993.                 {
  1994.                   if ( (vertex = *(connect++)-1) == -1) 
  1995.                     {
  1996.                       connect += i-1;
  1997.                       break;
  1998.                     }
  1999.                   PALETTECPACK(vcolor[vertex]);
  2000.                   v3f(pcoord[vertex]);
  2001.                 }
  2002.               endpolygon();
  2003.             }
  2004.           else 
  2005.             {
  2006.               /* Save connectivity pointer. */
  2007.               oconnect = connect;
  2008.  
  2009.               /* Draw the polygon. */
  2010.               cpack (0);
  2011.               bgnpolygon();
  2012.               for (i = nvert; i > 0; i--) 
  2013.                 {
  2014.                   if ( (vertex = *(connect++)-1) == -1) 
  2015.                     {
  2016.                       connect += i-1;
  2017.                       break;
  2018.                     }
  2019.                   
  2020.                   v3f(pcoord[vertex]);
  2021.                 }
  2022.               endpolygon();
  2023.  
  2024.               /* Start connectivity anew. */
  2025.               connect = oconnect;
  2026.  
  2027.               /* Squeeze the zbuffer. */
  2028.               set_squeezed_zbuffer ();
  2029.  
  2030.               /* Draw the outline of the polygon, with Z values */
  2031.               bgnclosedline();
  2032.               for (i = nvert; i > 0; i--) 
  2033.                 {
  2034.                   if ( (vertex = *(connect++)-1) == -1)
  2035.                     {
  2036.                       connect += i-1;
  2037.                       break;
  2038.                     }
  2039.                   PALETTECPACK(vcolor[vertex]);
  2040.                   v3f(pcoord[vertex]); 
  2041.                 }
  2042.               endclosedline();
  2043.  
  2044.               /* Restore the Zbuffer. */
  2045.               lsetdepth (gstate->zmax, gstate->zmin);
  2046.               
  2047.             }          
  2048.           if (picked) picked++;
  2049.           count--;
  2050.         }
  2051.       
  2052.     }
  2053.  
  2054.   linewidth (1);
  2055.   
  2056.   return ST_OKAY;
  2057. }
  2058.  
  2059.  
  2060.  
  2061.  
  2062.  
  2063. /* DRAW PICKED ELEMENTS */
  2064. int DrawPickedVertices(state_t *state, window_t *win, object_t *obj,
  2065.                        objinfo_t *info)
  2066. {
  2067.   float jackscale;
  2068.   long count;
  2069.   
  2070.   Vdata_t **vdata;
  2071.   Vdata_t *pcoord_v;
  2072.   
  2073.   float (*pcoord)[DIMS];
  2074.   char *picked;
  2075.   
  2076.   /* Get pointers to the pertinent data sets */
  2077.   vdata = obj->u.obj.vdata;
  2078.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2079.     return ST_OKAY;
  2080.  
  2081.   /* Set up the consolidated coordinate array pointer. */
  2082.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2083.   count = pcoord_v->stats[0].rec_count;
  2084.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2085.  
  2086.   /* Get a pointer to the pick list if the object is picked and it */
  2087.   /* is in the proper mode. */
  2088.   picked = OBJ_PICKLIST(obj);
  2089.   if (OBJ_PICKMODE(obj) != PICK_VERTEX)
  2090.     return ST_ERROR;
  2091.   
  2092.   jackscale = win->max_width / 100.0;
  2093.   /* No color information.  Use foreground and draw the */
  2094.   /* appropriate shapes. */
  2095.   cpack(FOREGROUND);
  2096.   while (count > 0) 
  2097.     {
  2098.       if (*picked)
  2099.         DrawJack(pcoord, jackscale);
  2100.     
  2101.       /* Move to the next x, y, z set and decrement the */
  2102.       /* count. */
  2103.       picked++;
  2104.       pcoord++;
  2105.       count--;
  2106.     }
  2107.   
  2108.   return ST_OKAY;
  2109. }
  2110.  
  2111.  
  2112. int DrawPickedFaces (state_t *state, window_t *win, object_t *obj, 
  2113.                      objinfo_t *info)
  2114. {
  2115.   long count;
  2116.   
  2117.   Vdata_t **vdata;
  2118.   Vdata_t *vcolor_v;
  2119.   Vdata_t *pcoord_v;
  2120.   Vdata_t *connect_v;
  2121.   
  2122.   float (*pcoord)[DIMS];
  2123.   int   *vcolor;
  2124.   int   *connect;
  2125.   char  *picked;
  2126.   
  2127.   int i, nvert, vertex;
  2128.   
  2129.   /* Get pointers to the pertinent data sets */
  2130.   vdata = obj->u.obj.vdata;
  2131.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  2132.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
  2133.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
  2134.       return draw_vertices(state, win, obj, info);
  2135.  
  2136.   /* If the plist does not describe polygons, draw edges. */
  2137.   if (connect_v->stats[0].rec_size < 3)
  2138.     return draw_edges(state, win, obj, info);
  2139.   
  2140.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2141.     return ST_OKAY;
  2142.     
  2143.   /* Collect connectivity information for drawing. */
  2144.   connect = (int *) connect_v->data;
  2145.   count = connect_v->stats[0].rec_count;
  2146.   nvert = connect_v->stats[0].rec_size;
  2147.     
  2148.   /* Set up the consolidated coordinate array pointer. */
  2149.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2150.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2151.     
  2152.   /* Get a pointer to the pick list if the object is picked and it */
  2153.   /* is in the proper mode. */
  2154.   picked = OBJ_PICKLIST(obj);
  2155.   if (OBJ_PICKMODE(obj) != PICK_FACE)
  2156.     return ST_ERROR;
  2157.   
  2158.   /* If there is no vertex color information, draw without it */
  2159.   /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  2160.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  2161.     {
  2162.       /* No color information.  Use foreground and draw the */
  2163.       /* appropriate shapes. */
  2164.       color(FOREGROUND);
  2165.       while (count > 0) 
  2166.         {
  2167.           if (*picked) 
  2168.             {
  2169.               bgnpolygon();
  2170.               for (i = nvert; i > 0; i--) 
  2171.                 {
  2172.                 if ( (vertex = *(connect++)-1) == -1) 
  2173.                   {
  2174.                     connect += i-1;
  2175.                     break;
  2176.                   }
  2177.                 
  2178.                 v3f(pcoord[vertex]);
  2179.               }
  2180.               endpolygon();
  2181.             }
  2182.           else 
  2183.             {
  2184.               connect += nvert;
  2185.             }
  2186.           
  2187.           if (picked) 
  2188.             picked++;
  2189.           count--;
  2190.         }
  2191.     }
  2192.   else 
  2193.     {
  2194.       /* Set pointers to the actual data and the size of the data */
  2195.       /* sets. */
  2196.       assert (vcolor_v->stats[0].type == PVINTEGER);
  2197.       
  2198.       /* There is color information.  Get it and use it to draw the */
  2199.       /* appropriate shapes. */
  2200.       vcolor = (int *) vcolor_v->data;
  2201.       while (count > 0) 
  2202.         {
  2203.           if (*picked) 
  2204.             {
  2205.               bgnpolygon();
  2206.               for (i = nvert; i > 0; i--) 
  2207.                 {
  2208.                   if ( (vertex = *(connect++)-1) == -1) 
  2209.                     {
  2210.                       connect += i-1;
  2211.                       break;
  2212.                     }
  2213.                   
  2214.                   PALETTECPACK(vcolor[vertex]);
  2215.                   v3f(pcoord[vertex]);
  2216.                 }
  2217.               endpolygon();
  2218.             }
  2219.           else 
  2220.             {
  2221.               connect += nvert;
  2222.             }
  2223.           
  2224.           if (picked) 
  2225.             picked++;
  2226.           count--;
  2227.         }
  2228.     }
  2229.   
  2230.   return ST_OKAY;
  2231. }
  2232.  
  2233.  
  2234. /* ------------------------------------------------------------------------ */
  2235. /* ----------------------- RAYSHADE OUTPUT ROUTINES ----------------------- */
  2236. /* ------------------------------------------------------------------------ */
  2237.  
  2238. static FILE *rayfp = NULL;
  2239.  
  2240. static void ray_bgnpolygon (void)
  2241. {
  2242.   fprintf (rayfp, "  poly \n");
  2243.   
  2244.   return;
  2245. }
  2246.  
  2247. static void ray_v3f (float *vv)
  2248. {
  2249.   fprintf (rayfp, "    %f %f %f\n", vv[0], vv[1], vv[2]);
  2250.   
  2251.   return;
  2252. }
  2253.  
  2254. static void ray_endpolygon (void)
  2255. {
  2256.   
  2257.   return;
  2258. }
  2259.  
  2260. static void ray_palettecpack (int c)
  2261. {
  2262.   fprintf (rayfp, "    pal%1d\n", c);
  2263.   
  2264.   return;
  2265. }
  2266.  
  2267.  
  2268. /* Keep a static array of vertices and a count of the number
  2269.    of vertices in the array. */
  2270. static float line_vv[20][3];
  2271. static int line_vv_count = 0;
  2272.  
  2273. static int line_cc[20];
  2274. static int line_cc_used = 0;
  2275.  
  2276. /* Static width of lines drawn as cylinders. */
  2277. static float line_width = 0.1;
  2278.  
  2279. /* This should be a window-local variable or something. */
  2280. static int cap_cylinders = 0;
  2281.  
  2282. static void ray_linepalettecpack (int c)
  2283. {
  2284.   /* Save this color index with the current vertex. */
  2285.   line_cc[line_vv_count] = c;
  2286.  
  2287.   /* Note that we are using colors for this line. */
  2288.   line_cc_used = 1;
  2289. }
  2290.  
  2291. static void ray_bgnclosedline (void)
  2292. {
  2293.   /* Starting a new line. */
  2294.   line_vv_count = 0;
  2295.   
  2296.   /* Haven't used any colors yet. */
  2297.   line_cc_used = 0;
  2298. }
  2299.  
  2300. static void ray_endclosedline (void)
  2301. {
  2302.   int i;
  2303.  
  2304.   /* If we have one or fewer vertices, punt. */
  2305.   if (line_vv_count < 2)
  2306.     goto done;
  2307.  
  2308.   /* For each vertex up to the second-to-last, make
  2309.      a cylinder with the vertex and its successor. */
  2310.   for (i = 0; i < line_vv_count - 1; i++)
  2311.     {
  2312.       fprintf (rayfp, "  cylinder\n");
  2313.  
  2314.       if (line_cc_used)
  2315.         {
  2316.           /* We've used colors, so set a color. */
  2317.           fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2318.         }
  2319.  
  2320.       fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2321.                /* radius */ "CYL_RAD",
  2322.                /* end 1  */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
  2323.                /* end 2  */ line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2]);
  2324.  
  2325.       if (cap_cylinders)
  2326.         {
  2327.           fprintf (rayfp, "  disc\n");
  2328.           if (line_cc_used)
  2329.             fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2330.           fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2331.                    "CYL_RAD",
  2332.                    line_vv[i][0], line_vv[i][1], line_vv[i][2],
  2333.                    line_vv[i][0] - line_vv[i+1][0],
  2334.                    line_vv[i][1] - line_vv[i+1][1],
  2335.                    line_vv[i][2] - line_vv[i+1][2]);
  2336.           fprintf (rayfp, "  disc\n");
  2337.           if (line_cc_used)
  2338.             fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2339.           fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2340.                    "CYL_RAD",
  2341.                    line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2],
  2342.                    line_vv[i+1][0] - line_vv[i][0],
  2343.                    line_vv[i+1][1] - line_vv[i][1],
  2344.                    line_vv[i+1][2] - line_vv[i][2]);
  2345.         }
  2346.     }
  2347.  
  2348.   /* If there's more than 2 vertices, close the line. */
  2349.   if (line_vv_count > 2)
  2350.     {
  2351.       i = line_vv_count - 1;
  2352.       
  2353.       fprintf (rayfp, "  cylinder\n");
  2354.       
  2355.       if (line_cc_used)
  2356.         {
  2357.           fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2358.         }
  2359.       
  2360.       fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2361.                /* radius */ "CYL_RAD",
  2362.                /* end 1  */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
  2363.                /* end 2  */ line_vv[0][0], line_vv[0][1], line_vv[0][2]);
  2364.       
  2365.       if (cap_cylinders)
  2366.         {
  2367.           fprintf (rayfp, "  disc\n");
  2368.           if (line_cc_used)
  2369.             fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2370.           fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2371.                    "CYL_RAD",
  2372.                    line_vv[i][0], line_vv[i][1], line_vv[i][2],
  2373.                    line_vv[i][0] - line_vv[0][0],
  2374.                    line_vv[i][1] - line_vv[0][1],
  2375.                    line_vv[i][2] - line_vv[0][2]);
  2376.           fprintf (rayfp, "  disc\n");
  2377.           if (line_cc_used)
  2378.             fprintf (rayfp, "    pal%1d\n", line_cc[i]);
  2379.           fprintf (rayfp, "    %s\n    %f %f %f\n    %f %f %f\n",
  2380.                    "CYL_RAD",
  2381.                    line_vv[0][0], line_vv[0][1], line_vv[0][2],
  2382.                    line_vv[0][0] - line_vv[i][0],
  2383.                    line_vv[0][1] - line_vv[i][1],
  2384.                    line_vv[0][2] - line_vv[i][2]);
  2385.         }
  2386.     }
  2387.   
  2388.  done:
  2389.   line_vv_count = 0;
  2390.   return;
  2391. }
  2392.  
  2393.  
  2394. static void ray_linev3f (float *vv)
  2395. {
  2396.   /* Store this vertex. */
  2397.   line_vv[line_vv_count][0] = vv[0];
  2398.   line_vv[line_vv_count][1] = vv[1];
  2399.   line_vv[line_vv_count][2] = vv[2];
  2400.  
  2401.   /* Increment the count. */
  2402.   line_vv_count++;
  2403.  
  2404.   return;
  2405. }
  2406.  
  2407.  
  2408. /* ------------------------------------------------------------------------ */
  2409. /* ------------------------ SPHERE RAY/GL ROUTINES ------------------------ */
  2410. /* ------------------------------------------------------------------------ */
  2411.  
  2412. static float sphere_size;
  2413.  
  2414. /* 1 if vertices should be drawn as cubes. */
  2415. static int sphere_cubes;
  2416.  
  2417. static int sphere_col_set = 0;
  2418. static int sphere_col;
  2419.  
  2420. static void ray_sphpalettecpack (int c)
  2421. {
  2422.   sphere_col_set = 1;
  2423.   sphere_col = c;
  2424.  
  2425.   return;
  2426. }
  2427.  
  2428.  
  2429. static void ray_sphdraw (float *vv)
  2430. {
  2431.   if (sphere_cubes)
  2432.     {
  2433.       fprintf (rayfp, "  box\n");
  2434.       if (sphere_col_set)
  2435.         fprintf (rayfp, "    pal%1d\n", sphere_col);
  2436.       fprintf (rayfp, "    (%f-SPH_RAD) (%f-SPH_RAD) (%f-SPH_RAD)\n",
  2437.                vv[0],
  2438.                vv[1],
  2439.                vv[2]);
  2440.       fprintf (rayfp, "    (%f+SPH_RAD) (%f+SPH_RAD) (%f+SPH_RAD)\n",
  2441.                vv[0],
  2442.                vv[1],
  2443.                vv[2]);
  2444.     }
  2445.   else
  2446.     {
  2447.       fprintf (rayfp, "  sphere\n");
  2448.       if (sphere_col_set)
  2449.         fprintf (rayfp, "    pal%1d\n", sphere_col);
  2450.       fprintf (rayfp, "    %s\n", "SPH_RAD");
  2451.       fprintf (rayfp, "    %f %f %f\n", vv[0], vv[1], vv[2]);
  2452.     }
  2453.  
  2454.   /* Make sure we don't repeat a color. */
  2455.   sphere_col_set = 0;
  2456.  
  2457.   return;
  2458. }
  2459.  
  2460.  
  2461.  
  2462.  
  2463. static int ray_draw_vertices (state_t *state, window_t *win, object_t *obj, 
  2464.                            objinfo_t *info)
  2465. {
  2466.   long    count;
  2467.   
  2468.   Vdata_t **vdata;
  2469.   Vdata_t *vcolor_v;
  2470.   Vdata_t *pcoord_v;
  2471.   
  2472.   float    (*pcoord)[DIMS];
  2473.   int *vcolor;
  2474.   char *picked;
  2475.  
  2476.   int single_color;
  2477.   
  2478.   /* Get pointers to the pertinent data sets */
  2479.   vdata = obj->u.obj.vdata;
  2480.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  2481.   if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2482.     return ST_OKAY;
  2483.  
  2484.   /* Set up the consolidated coordinate array pointer. */
  2485.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2486.   count = pcoord_v->stats[0].rec_count;
  2487.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2488.  
  2489.   if (FEQ(win->sphere_size, 0.0))
  2490.     sphere_size = win->max_width * 0.01;
  2491.   else
  2492.     sphere_size = win->sphere_size;
  2493.  
  2494.   fprintf (rayfp, "#define SPH_RAD %f\n", sphere_size);
  2495.  
  2496.   sphere_cubes = (win->sphere_depth == 1);
  2497.  
  2498.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  2499.     {
  2500.       /* No color information.  Use foreground and draw the */
  2501.       /* appropriate shapes. */
  2502.       while (count > 0) 
  2503.         {
  2504.           { /* not selected */
  2505.             float params[4];
  2506.             
  2507.             params[0] = (*pcoord)[0];
  2508.             params[1] = (*pcoord)[1];
  2509.             params[2] = (*pcoord)[2];
  2510.             params[3] = win->sphere_size;
  2511.             
  2512.             ray_sphdraw (params);
  2513.           }
  2514.           
  2515.           /* Move to the next x, y, z set and decrement the */
  2516.           /* count. */
  2517.           pcoord++;
  2518.           count--;
  2519.         }
  2520.     }
  2521.   else 
  2522.     {
  2523.       /* Set pointers to the actual data and the size of the data */
  2524.       /* sets. */
  2525.       assert (vcolor_v->stats[0].type == PVINTEGER);
  2526.       
  2527.       /* There is color information.  Get it and use it to draw the */
  2528.       /* appropriate shapes. */
  2529.       vcolor = (int *) vcolor_v->data;
  2530.       
  2531.       while (count > 0) 
  2532.         {
  2533.           { /* not selected */
  2534.             float params[4];
  2535.             
  2536.             ray_sphpalettecpack(*vcolor);
  2537.             
  2538.             params[0] = (*pcoord)[0];
  2539.             params[1] = (*pcoord)[1];
  2540.             params[2] = (*pcoord)[2];
  2541.             params[3] = win->sphere_size;
  2542.             
  2543.             ray_sphdraw (params);      
  2544.           }
  2545.           /* Move to the next x, y, z set, color entry, and */
  2546.           /* decrement the count. */
  2547.           pcoord++;
  2548.           vcolor++;
  2549.           count--;
  2550.         }
  2551.     }
  2552.  
  2553.   return ST_OKAY;
  2554. }
  2555.  
  2556. static int ray_draw_edges (state_t *state, window_t *win, object_t *obj, 
  2557.                            objinfo_t *info)
  2558. {
  2559.   long count;
  2560.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  2561.   float (*pcoord)[DIMS];
  2562.   int *vcolor, *connect;
  2563.   char *picked;
  2564.   int i, nvert, vertex;
  2565.  
  2566.   /* Set the width of the cylinders. */
  2567.   line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
  2568.  
  2569.   fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
  2570.  
  2571.   /* Get pointers to the pertinent data sets. */
  2572.   vdata = obj->u.obj.vdata;
  2573.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  2574.   if ((connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  2575.     if ((connect_v = get_vdata(state, vdata[MCONNECT])) == NULL) 
  2576.       {
  2577.         ray_draw_vertices(state, win, obj, info);
  2578.         return ST_OKAY;
  2579.       }
  2580.   if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2581.     return ST_OKAY;
  2582.   
  2583.   /* Collect connectivity information for drawing. */
  2584.   connect = (int *) connect_v->data;
  2585.   count = connect_v->stats[0].rec_count;
  2586.   nvert = connect_v->stats[0].rec_size;
  2587.   
  2588.   /* Set up the consolidated coordinate array pointer. */
  2589.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2590.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2591.   
  2592.   /* If there is no vertex color information, draw without it */
  2593.   /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  2594.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  2595.     {
  2596.       /* No color information.  Use foreground and draw the */
  2597.       /* appropriate shapes. */
  2598.       while (count > 0) 
  2599.         {
  2600.           ray_bgnclosedline();
  2601.           
  2602.           for (i = nvert; i > 0; i--) 
  2603.             {
  2604.               if ( (vertex = *(connect++)-1) == -1) 
  2605.                 {
  2606.                   connect += i-1;
  2607.                   break;
  2608.                 }
  2609.               ray_linev3f(pcoord[vertex]);
  2610.             }
  2611.           
  2612.           ray_endclosedline();
  2613.           
  2614.           count--;
  2615.         }
  2616.     }
  2617.   else 
  2618.     {
  2619.       /* Set pointers to the actual data and the size of the data */
  2620.       /* sets. */
  2621.       assert (vcolor_v->stats[0].type == PVINTEGER);
  2622.       
  2623.       /* There is color information.  Get it and use it to draw the */
  2624.       /* appropriate shapes. */
  2625.       vcolor = (int *) vcolor_v->data;
  2626.       while (count > 0) 
  2627.         {
  2628.           ray_bgnclosedline();
  2629.           
  2630.           for (i = nvert; i > 0; i--) 
  2631.             {
  2632.               if ( (vertex = *(connect++)-1) == -1) 
  2633.                 {
  2634.                   connect += i-1;
  2635.                   break;
  2636.                 }
  2637.  
  2638.               ray_linepalettecpack(vcolor[vertex]);
  2639.               ray_linev3f(pcoord[vertex]);
  2640.             }
  2641.           
  2642.           ray_endclosedline();
  2643.           
  2644.           count--;
  2645.         }
  2646.     }
  2647.  
  2648.   return ST_OKAY;
  2649. }
  2650.  
  2651.  
  2652. static int ray_draw_faces (state_t *state, window_t *win, object_t *obj, 
  2653.                            objinfo_t *info)
  2654. {
  2655.   long count;
  2656.   
  2657.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  2658.     
  2659.   float    (*pcoord)[DIMS];
  2660.   int *vcolor, *connect;
  2661.   char *picked;
  2662.   
  2663.   int i, nvert, vertex, single_color;
  2664.   
  2665.   /* Get pointers to the pertinent data sets */
  2666.   vdata = obj->u.obj.vdata;
  2667.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  2668.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
  2669.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
  2670.       return ray_draw_vertices(state, win, obj, info);
  2671.   
  2672.   /* If the plist does not describe polygons, draw edges. */
  2673.   if (connect_v->stats[0].rec_size < 3)
  2674.     return ray_draw_edges(state, win, obj, info);
  2675.   
  2676.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2677.     return ST_OKAY;
  2678.   
  2679.   /* Collect connectivity information for drawing. */
  2680.   connect = (int *) connect_v->data;
  2681.   count = connect_v->stats[0].rec_count;
  2682.   nvert = connect_v->stats[0].rec_size;
  2683.   
  2684.   /* Set up the consolidated coordinate array pointer. */
  2685.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2686.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2687.   
  2688.   /* If there is no vertex color information, draw without it */
  2689.   /* (use the FOREGROUND color).  Otherwise, grab the color array. */
  2690.  
  2691.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  2692.     {
  2693.       while (count > 0) 
  2694.         {
  2695.           ray_bgnpolygon();
  2696.           for (i = nvert; i > 0; i--) 
  2697.             {
  2698.               if ( (vertex = *(connect++)-1) == -1) 
  2699.                 {
  2700.                   connect += i-1;
  2701.                   break;
  2702.                 }
  2703.               ray_v3f(pcoord[vertex]);
  2704.             }
  2705.           ray_endpolygon();
  2706.           
  2707.           count--;
  2708.         }
  2709.     }
  2710.   else 
  2711.     {
  2712.       /* Set pointers to the actual data and the size of the data */
  2713.       /* sets. */
  2714.       assert (vcolor_v->stats[0].type == PVINTEGER);
  2715.       
  2716.       /* There is color information.  Get it and use it to draw the */
  2717.       /* appropriate shapes. */
  2718.       vcolor = (int *) vcolor_v->data;
  2719.  
  2720.       while (count > 0) 
  2721.         {
  2722.           ray_bgnpolygon();
  2723.           for (i = nvert; i > 0; i--) 
  2724.             {
  2725.               if ((vertex = *(connect++)-1) == -1) 
  2726.                 {
  2727.                   connect += i-1;
  2728.                   break;
  2729.                 }
  2730.               
  2731.               if (i == nvert)
  2732.                 ray_palettecpack (vcolor[vertex]);
  2733.  
  2734.               ray_v3f(pcoord[vertex]);
  2735.             }
  2736.           ray_endpolygon();
  2737.           
  2738.           count--;
  2739.         }
  2740.  
  2741.     }
  2742.   
  2743.   return ST_OKAY;
  2744. }
  2745.  
  2746.  
  2747.  
  2748. static int ray_draw_outlined_faces(state_t *state, window_t *win, 
  2749.                                    object_t *obj,
  2750.                                    objinfo_t *info)
  2751. {
  2752.   long count;
  2753.   
  2754.   Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
  2755.   
  2756.   float (*pcoord)[DIMS];
  2757.   float pcoord_outline[DIMS];
  2758.   int *vcolor, *connect, *oconnect;
  2759.   char *picked;
  2760.   int i, j, nvert, vertex, single_color;
  2761.  
  2762.   /* Set the width of the cylinders. */
  2763.   line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
  2764.  
  2765.   fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
  2766.  
  2767.   /* Get pointers to the pertinent data sets */
  2768.   vdata = obj->u.obj.vdata;
  2769.   vcolor_v = get_vdata(state, vdata[VCOLOR]);
  2770.   if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL) 
  2771.     if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL) 
  2772.       return ray_draw_vertices(state, win, obj, info);
  2773.  
  2774.   /* If the plist does not describe polygons, draw edges. */
  2775.   if (connect_v->stats[0].rec_size < 3)
  2776.     return ray_draw_edges(state, win, obj, info);
  2777.   
  2778.   if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
  2779.     return ST_OKAY;
  2780.   
  2781.   /* Collect connectivity information for drawing. */
  2782.   oconnect = connect = (int *) connect_v->data;
  2783.   count = connect_v->stats[0].rec_count;
  2784.   nvert = connect_v->stats[0].rec_size;
  2785.   
  2786.   /* Set up the consolidated coordinate array pointer. */
  2787.   pcoord = (float (*)[DIMS]) pcoord_v->data;
  2788.   
  2789.   assert (pcoord_v->stats[0].type == PVFLOAT);
  2790.   
  2791.   /* If there is no vertex color information, draw without it. */
  2792.   /* Otherwise, grab the color array. */
  2793.   if (vcolor_v == NULL || vcolor_v->data == NULL) 
  2794.     {
  2795.       while (count > 0)
  2796.         {
  2797.           /* Save connectivity pointer. */
  2798.           oconnect = connect;
  2799.           
  2800.           /* Draw the polygon. */
  2801.           ray_bgnpolygon();
  2802.           for (i = nvert; i > 0; i--) 
  2803.             {
  2804.               if ( (vertex = *(connect++)-1) == -1) 
  2805.                 {
  2806.                   connect += i-1;
  2807.                   break;
  2808.                 }
  2809.               
  2810.               ray_v3f(pcoord[vertex]);
  2811.             }
  2812.           ray_endpolygon();
  2813.           
  2814.           /* Start connectivity anew. */
  2815.           connect = oconnect;
  2816.           
  2817.           /* Draw the outline of the polygon, with Z values */
  2818.           ray_bgnclosedline();
  2819.           for (i = nvert; i > 0; i--) 
  2820.             {
  2821.               if ( (vertex = *(connect++)-1) == -1)
  2822.                 {
  2823.                   connect += i-1;
  2824.                   break;
  2825.                 }
  2826.               ray_linev3f(pcoord[vertex]); 
  2827.             }
  2828.           ray_endclosedline();
  2829.           
  2830.           count--;
  2831.         }
  2832.       
  2833.     }
  2834.   else 
  2835.     {
  2836.       /* Set pointers to the actual data and the size of the data */
  2837.       /* sets. */
  2838.       assert (vcolor_v->stats[0].type == PVINTEGER);
  2839.       
  2840.       /* There is color information.  Get it and use it to draw the */
  2841.       /* appropriate shapes. */
  2842.       vcolor = (int *) vcolor_v->data;
  2843.  
  2844.       while (count > 0) 
  2845.         {
  2846.           /* Save connectivity pointer. */
  2847.           oconnect = connect;
  2848.           
  2849.           /* Draw the polygon. */
  2850.           ray_bgnpolygon();
  2851.           for (i = nvert; i > 0; i--) 
  2852.             {
  2853.               if ( (vertex = *(connect++)-1) == -1) 
  2854.                 {
  2855.                   connect += i-1;
  2856.                   break;
  2857.                 }
  2858.               if (i == nvert)
  2859.                 ray_palettecpack(vcolor[vertex]);
  2860.               ray_v3f(pcoord[vertex]);
  2861.             }
  2862.           ray_endpolygon();
  2863.           
  2864.           /* Start connectivity anew. */
  2865.           connect = oconnect;
  2866.           
  2867.           /* Draw the outline of the polygon, with Z values */
  2868.           ray_bgnclosedline();
  2869.           for (i = nvert; i > 0; i--) 
  2870.             {
  2871.               if ( (vertex = *(connect++)-1) == -1)
  2872.                 {
  2873.                   connect += i-1;
  2874.                   break;
  2875.                 }
  2876.               ray_linev3f(pcoord[vertex]); 
  2877.             }
  2878.           ray_endclosedline();
  2879.           
  2880.           count--;
  2881.         }
  2882.       
  2883.     }
  2884.   
  2885.   return ST_OKAY;
  2886. }
  2887.  
  2888.